簡體   English   中英

比較2個文件並刪除file2中與file1中找到的值匹配的任何行

[英]Compare 2 files and remove any lines in file2 when they match values found in file1

我有兩個文件。 我試圖刪除文件2中的任何行,當它們匹配file1中找到的值。 一個文件有這樣的列表:

文件1

ZNI008
ZNI009
ZNI010
ZNI011
ZNI012

...超過19463行

第二個文件包含與第一個文件中列出的項匹配的行: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'

只顯示一場比賽,即使我可以清楚地看到有多場比賽。

或者將所有數據放入一個文件並運行以下命令:

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

說論證有太多的線要處理。

我需要從file2中刪除與file1中的項匹配的行。

我也在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,

`

它運行不正常..因為我正在獲取'Traceback(最近的呼叫最后一次):文件“./test.py”,第14行,在? 如果字段[1]不在s中:IndexError:列表索引超出范圍'

關於什么:

grep -F -v -f file1 file2 > file3

我更喜歡byrondrossos的grep解決方案,但這是另一種選擇:

sed $(awk '{printf("-e /%s/d ", $1)}' file1) file2 > file3

這是因為-i開關使用BashGNU sed

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

這會利用shell評估順序


好吧,我想這個想法的正確方法是使用ed 這也應該是POSIX。

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

在任何情況下, grep似乎都是適合這項工作的工具。
@byrondrossos答案應該對你有用;)

這無疑是丑陋的,但確實有效。 但是,所有的路徑必須相同(當然除了ZNI ###部分)。 除了路徑的ZNI ###之外的所有內容都被刪除,因此命令grep -vf可以在已排序的文件上正確運行。

首先將“testfile2”轉換為“testfileconverted”以顯示ZNI ###

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

第二次使用轉換后的文件的反grep與“testfile1”相比較,並將重新格式化的輸出添加到“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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM