web-dev-qa-db-ja.com

grepコマンドで文字列検索をifステートメントに入れる方法は?

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シェルを使用しています。

前もって感謝します。

11
Mareyes

これを試して:

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演算子を使用する必要はありません。
11
msp9011

別のオプション:

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
13
glenn jackman
_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を個別に実行することもできます。 (grepwcの起動オーバーヘッドの違いは、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]}_の省略形です。

2
Peter Cordes