他のファイルで見つかった行に基づいてファイルから行を削除する

他のファイルで見つかった行に基づいてファイルから行を削除する

file1.txt ファイルには次の行が含まれています。

/api/purchase/<hash>/index.html

たとえば、

/api/purchase/12ab09f46/index.html

file2.csv ファイルには次の行が含まれています。

<hash>,timestamp,ip_address

たとえば、

12ab09f46,20150812235200,22.231.113.64 
a77b3ff22,20150812235959,194.66.82.11

file2.csvをフィルタリングし、file1.txtからハッシュ値も存在するすべての行を削除したいと思います。言い換えれば:

cat file1.txt | extract <hash> | sed '/<hash>/d' file2.csv

またはそのようなもの。

簡単なはずですが、うまく機能しないようです。

誰もがこのタスクに対して機能するパイプラインを提供できますか?

答え1

cut -d / -f 4 file1.txt | paste -sd '|' | xargs -I{} grep -v -E {} file2.csv

説明する:

cut -d / -f 4 file1.txtハッシュ値は最初のファイルから選択されます。

paste -sd '|'すべてのハッシュ値を正規表現に連結します。H1|H2|H3

xargs -I{} grep -v -E {} file2.csv{}grepは前のパターンを引数として使用され、xargsは次のように置き換えられます。STDIN

ない場合は、paste代替品に置き換えてください。tr "\\n" "|" | sed 's/|$//'

答え2

考えられるawk解決策:

awk 'NR == FNR { x[$4] = 1; next; } { if (!($1 in x)) print $0; }' FS="/" file1.txt FS="," file2.txt

まず、(フィールド区切り文字)「/」file1.txtを使用して読み込み、必要なハッシュ値であるフィールドFSのキー値で配列xを作成します。次に、2番目のファイル設定を$4読み取り、フィールド値が配列のキーとして存在しないことを確認し、存在しない場合は印刷します。コメントで提案されたより慣用的な声明は次のとおりです。file2.txtFS,$1x

awk 'NR == FNR { x[$4] = 1; next; } !($1 in x)' FS="/" file1.txt FS="," file2.txt

答え3

~のためGNU sed

sed -z 's%.*/\([^/]*\)/index.html\n%\1\\|%g;s%^%/%;s%\\|$%/d%' file1.csv |
sed -f - file2.csv

どこ最初 sedsed-command-formatでハッシュリストを生成し、/12ab09f46\|a77b3ff22\|..../d次に送信します。Next sed-script は入力から上記のコマンドを読み取るので-f -オプションです。
同じgrep

grep -oP '[^/]*(?=/index.html$)' file1.csv | grep -Fvf - file2.csv

またはPerl式なし:

grep -o '[^/]*/index.html$' file1.csv | 
grep -o '^[^/]*' | 
grep -Fvf - file2.csv

またはより良い切る:

cut -d/ -f4 file1.csv | grep -Fvf - file2.csv

答え4

次の裏地のいずれかを試してみましたが、効果があるようです。

 for i in `cat file1.txt  | awk -F"/" '{print $4}'`; do echo "\n $i" ; sed -ri "/^$i,/d" file2.csv ; done

まず交換してください- 内部そして- についてそれをテストするため。- についてテスト実行を実行し、すべてが正常に機能したら実行できます。- 内部

関連情報