ファイルがあります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
-F
grep
いいえ数値を正規表現として解釈しますが、固定文字列では解釈しません。-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
ために数字が一致することです。sed
grep
どこかに行の観点から、間違った行を削除することもできます。データ内の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
各行を印刷します。~