sedコマンドの使用中にパターンに変数を渡すには?

sedコマンドの使用中にパターンに変数を渡すには?

ファイルがありますabc.sh

search_dir='dummy'
filename='numbers.txt'

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed -i '' "/$p/d" $entry
  done < $filename
done

パターンが一致する行を削除してみてください。デフォルトでは、パターンはファイルから渡される文字列にすぎません。しかし、残念ながら動作しません。

私がデバッグできたのは、正しいモードで変数を渡さなかったことです。

編集する: 数値.txt

2018061300006178
2018061300006179
2018061300006325
2018061300006326
2018061400006505

search_dirのファイルの内容は次のとおりです。

1888~2018061400006505~0101~1~OWNED~SELF EMPLOYED~~~~3~~AGRICULTURE~~~OTHERS~AGRICULTURIST~~~AGRICULTURE~~~~~~~~N~N~Y~N~N~~300000-500000~~~49582E95361D5FA0C10C4C419B2940591C17E94EF329C31047A6B7DE26E68638
1889~2018061400006505~0101~2~OWNED~SELF EMPLOYED~~~~32~~AGRICULTURE~~~OTHERS~AGRIC

だからNumbers.txtには2018061400006505が含まれており、ファイルには数値関連データも含まれているので、与えられた数値に一致する行を削除したいと思います。

答え1

sed例の数字に使用中の区切り記号(デフォルト/)が含まれていない限り、コードの正規表現$p(すべての意味を含む)として解釈されます。

あなたのコード:

search_dir='dummy'
filename='numbers.txt'

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed -i '' "/$p/d" $entry
  done < $filename
done

$search_dirここでは、数値を含むファイルのすべての行を削除しようとしています$filename。これが有効かどうかは治療sed方法によって異なります-i ''。一部の実装では、引数なしで使用する必要sedがあります。-i

関連性sed -iと移植性:sed -i(所定の位置で編集)を使用して移植性を達成するには?

結果を一時ファイルに書き込み、そのファイルを元のファイル名に移動する方が安全です。

for entry in "$search_dir"/*
do
  while read p;
  do 
    sed "/$p/d" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
  done <"$filename"
done

これにより、sedどの実装を使用しても正しく機能することができます。一般的に言えば、スクリプトをテストするときにファイルを内部的に変更しようとするのは悪いことですmv

一般的な解決策として、これは本質的に「データをコードとして使用する」ため、まだ少し安全ではありません(数字はデータであり、それをsedスクリプトの一部として使用しています)。つまり、数値ファイルの数字に を挿入するsedだけで、スクリプトで構文エラーが発生しやすくなります。/

作業は非常に簡単なので、代わりに使用できますgrep。これにより、内部whileループも削除されます。

for entry in "$search_dir"/*
do
  grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done

これにより、grepそのパターンがファイルから読み取られ、ファイル$filenameに適用されます。パターンを含む行はすべて削除します。$entry-v-Fgrepいいえ数値を正規表現として解釈しますが、固定文字列では解釈しません。-f "$filename"私たちはgrepそれから$filename

以下のディレクトリがある場合は、$search_dir次のディレクトリをスキップしたいと思います。

for entry in "$search_dir"/*
do
  [ ! -f "$entry" ] && continue
  grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done

もう一つの安全な方法は、上記と解決策のawkために数字が一致することです。sedgrepどこかに行の観点から、間違った行を削除することもできます。データ内の2番目に区切られたフィールドをawk簡単に一致させることができます。~

for entry in "$search_dir"/*; do
    [ ! -f "$entry" ] && continue
    awk -F '~' 'NR==FNR { num[$0]; next } !($2 in num)' "$filename" "$entry" >"$entry.tmp" &&
    mv "$entry.tmp" "$entry"
done

プログラムawkは最初に数値をキーとして連想配列/ハッシュを入力し、次に2番目の区切り列がそのハッシュのキーではなくファイルの$entry各行を印刷します。~

関連情報