2

2つのファイルがあります。file1で見つかった値と一致する場合、file2の行を削除しようとしています。1つのファイルには次のようなリストがあります。

File1

ZNI008
ZNI009
ZNI010
ZNI011
ZNI012

...19463行以上

2番目のファイルには、最初にリストされた項目に一致する行が含まれています:File2

copy /Y \\server\foldername\version\20050001_ZNI008_162635.xml \\server\foldername\version\folder\
copy /Y \\server\foldername\version\20050001_ZNI010_162635.xml \\server\foldername\version\folder\
copy /Y \\server\foldername\version\20050001_ZNI012_162635.xml \\server\foldername\version\folder\
copy /Y \\server\foldername\version\20050001_ZNI009_162635.xml \\server\foldername\version\folder\

...行51360までリストを続けます

私がこれまでに試したこと:

grep -v -i -f file1.txt file2.txt > f3.txt

f3.txt行への出力を生成したり、行を削除したりすることはありません。実行して確認しました

wc -l file2.txt

結果は

51360 file2.txt

その理由は、完全に一致するものがないためだと思います。次を実行すると何も表示されません

comm -1 -2 file1.txt file2.txt

ランニング

( tr '\0' '\n' < file1.txt; tr '\0' '\n' < file2.txt ) | sort | uniq -c | egrep -v '^ +1'

複数の一致があることがはっきりとわかりますが、は1つの一致のみを示しています。

または、すべてのデータを1つのファイルに入れて、以下を実行します。

grep -Ev "$(cat file1.txt)" 1>LinesRemoved.log

引数の行数が多すぎて処理できないと言います。

file1の項目に一致する行をfile2から削除する必要があります。

私もPythonでこれを試しています: `

    #!/usr/bin/python
s = set()

# load each line of file1 into memory as elements of a set, 's'
f1 = open("file1.txt", "r")
for line in f1:
    s.add(line.strip())
f1.close()

# open file2 and split each line on "_" separator,
# second field contains the value ZNIxxx
f2 = open("file2.txt", "r")
for line in f2:
    if line[0:4] == "copy":
        fields = line.split("_")
        # check if the field exists in the set 's'
        if fields[1] not in s:
            match = line
        else:
            match = 0
    else:
        if match:
            print match, line,

`

それはうまく機能していません..imgeting'Traceback(最後の最後の呼び出し):ファイル "./test.py"、14行目?fields [1]がsにない場合:IndexError:リストインデックスが範囲外です '

4

4 に答える 4

10

どうですか:

grep -F -v -f file1 file2 > file3
于 2012-04-18T13:22:47.613 に答える
1

byrondrossos の grep ソリューションの方が気に入っていますが、別のオプションがあります。

sed $(awk '{printf("-e /%s/d ", $1)}' file1) file2 > file3
于 2012-04-18T22:16:04.050 に答える
0

これは確かに醜いですが、うまくいきます。ただし、パスはすべて (もちろん ZNI### 部分を除く) で同じでなければなりません。パスの ZNI### 以外はすべて削除されるため、コマンド grep -vf はソートされたファイルに対して正しく実行できます。

最初に「testfile2」を「testfileconverted」に変換して、ZNI### のみを表示します。

cat /testfile2 | sed 's:^.*_ZNI:ZNI:g' | sed 's:_.*::g' > /testfileconverted

次に、「testfile1」と比較して変換されたファイルの逆 grep を使用し、再フォーマットされた出力を「testfile3」に追加します。

bash -c 'grep -vf <(sort /testfileconverted) <(sort /testfile1)' | sed "s:^:\copy /Y \\\|server\\\foldername\\\version\\\20050001_:g" | sed "s:$:_162635\.xml \\\|server\\\foldername\\\version\\\folder\\\:g" | sed "s:|:\\\:g" > /testfile3
于 2012-04-18T16:12:54.217 に答える
0

スイッチのため、これはBashGNU sedを使用しています-i

cp file2 file3
while read -r; do
    sed -i "/$REPLY/d" file3
done < file1

確かにもっと良い方法がありますが、ここにハックがあります-i :D

cp file2 file3
while read -r; do
    (rm file3; sed "/$REPLY/d" > file3) < file3
done < file1

これはシェルの評価順序を利用します


わかりました、このアイデアの正しい方法は を使用することだと思いますed。これもPOSIXである必要があります。

cp file2 file3
while read -r line; do
    ed file3 <<EOF
/$line/d
wq
EOF
done < file1

いずれにせよ、grep仕事に適したツールのようです。
@byrondrossosの答えはうまくいくはずです;)

于 2012-04-18T13:20:47.533 に答える