2つのファイルで複数の文字列を検索したい。両方のファイルで1つの文字列が見つかった場合は、何かを作成します。 1つの文字列が1つのファイルだけで見つかった場合は、別の文字列を作成します。
私のコマンドは次のとおりです:
####This is for the affirmative sentence in both files
if grep -qw "$users" "$file1" && grep -qw "$users" "$file2"; then
####This is for the affirmative sentence in only one file, and negative for the other one
if grep -qw "$users" "$file1" ! grep -qw "$users" "$file2"; then
それは声明を否定して肯定する正しい方法ですか? p.d. KSHシェルを使用しています。
前もって感謝します。
これを試して:
if grep -wq -- "$user" "$file1" && grep -wq -- "$user" "$file2" ; then
echo "string avail in both files"
Elif grep -wq -- "$user" "$file1" "$file2"; then
echo "string avail in only one file"
fi
grep
は複数のファイルのパターンを検索できるため、OR/NOT演算子を使用する必要はありません。別のオプション:
grep -qw -- "$users" "$file1"; in_file1=$?
grep -qw -- "$users" "$file2"; in_file2=$?
case "${in_file1},${in_file2}" in
0,0) echo found in both files ;;
0,*) echo only in file1 ;;
*,0) echo only in file2 ;;
*) echo in neither file ;;
esac
_n=0
#Or if you have more files to check, you can put your while here.
grep -qw -- "$users" "$file1" && ((n++))
grep -qw -- "$users" "$file2" && ((n++))
case $n in
1)
echo "Only one file with the string"
;;
2)
echo "The two files are with the string"
;;
0)
echo "No one file with the string"
;;
*)
echo "Strange..."
;;
esac
_
注:_((n++))
_はksh拡張機能です(zsh
およびbash
でもサポートされています)。 POSIX sh
構文では、代わりにn=$((n + 1))
が必要です。
ファイル名に改行が含まれていない場合は、grepで一致するファイルの名前を出力して結果をカウントすることで、grep
の複数回の呼び出しを回避できます。
_ local IFS=$'\n' # inside a function. Otherwise use some other way to save/restore IFS
matches=( $(grep -lw "$users" "$file1" "$file2") )
_
一致の数は_"${#matches[@]}"
_です。
ここに_grep --null -lw
_を使用する方法があるかもしれませんが、出力を解析する方法がわかりません。 Bash var=( array elements )
には、_\0
_の代わりに_\n
_区切り文字を使用する方法がありません。多分bashのmapfile
ビルトインがそれを行うことができますか?ただし、区切り文字は_-d string
_で指定するため、おそらくそうではありません。
count=$(grep -l | wc -l)
も可能ですが、2つの外部プロセスがあるため、2つのファイルに対してgrep
を個別に実行することもできます。 (grep
とwc
の起動オーバーヘッドの違いは、fork + exec +動的リンカーのものと比較して、個別のプロセスを起動する場合と比べるとわずかです)。
また、_wc -l
_では、一致するファイルを見つけることができません。
配列にキャプチャされた結果を使用して、それがすでに希望どおりであるか、または一致が1つだけの場合は、それが最初の入力であったかどうかを確認できます。
_local IFS=$'\n' # inside a function. Otherwise use some other way to save/restore IFS
matches=( $(grep -lw "$users" "$file1" "$file2") )
# print the matching filenames
[[ -n $matches ]] && printf 'match in %s\n' "${matches[@]}"
# figure out which input position the name came from, if there's exactly 1.
if [[ "${#matches[@]" -eq 1 ]]; then
if [[ $matches == "$file1" ]];then
echo "match in file1"
else
echo "match in file2"
fi
fi
_
_$matches
_は、最初の配列要素_${matches[0]}
_の省略形です。