如何从另一个文件中删除具有匹配模式的行?

时间:2019-03-03 00:02:20

标签: bash shell scripting tcl

我要删除FILE1中包含FILE2中模式的行。
我该如何使用shell / bash或Tcl?

例如:

文件1:

This is ECO_01  
This is ECO_02  
This is ECO_03  
This is ECO_04

FILE2:

ECO_02  
ECO_04  

输出:

This is ECO_01   
This is ECO_03  

4 个答案:

答案 0 :(得分:2)

在Tcl中,您将加载模式文件,然后使用它们进行过滤。保持主过滤流从标准输入到标准输出可能是最简单的。您可以轻松地将它们从文件重定向到文件。由于您似乎想使用“是模式的子字符串”作为匹配规则,因此可以使用string first进行操作,从而得到以下代码:

# Load in the patterns from the file named by the first argument
set f [open [lindex $argv 0]]
set patterns [split [string trimright [read $f] \n] \n]
close $f

# Factor out the actual matching
proc matches {theString} {
    global patterns
    foreach pat $patterns {
        # Change the next line to use other matching rules
        if {[string first $pat $theString] >= 0} {
            return true
        }
    }
    return false
}

# Read all input lines and print all non-matching lines
while {[gets stdin line] >= 0} {
    if {![match $line]} {
        puts $line
    }
}

我发现将关键步骤分解为程序很有帮助,例如“此行是否与我的任何模式都匹配?”,您可能会这样调用上述代码:

tclsh doFiltering.tcl patterns.txt <input.txt >output.txt

答案 1 :(得分:1)

最通用的解决方案是

$ grep -vf file2 file1

请注意,在任何字段上匹配的任何子字符串都将计数。如果您只限制在完全相同的字段(此处假定为最后一个)上完全匹配

$ awk 'NR==FNR{a[$1]; next} !($NF in a)' file2 file1

答案 2 :(得分:0)

您只需要使用 sed 命令(如下所示)从FILE1中删除匹配的行即可。

macOS:

for i in `cat FILE2.txt`
do
sed -i '' "/$i/d" FILE1.txt
done

Linux:

for i in `cat FILE2.txt`
do
sed -i '/$i/d' FILE1.txt
done

答案 3 :(得分:0)

另一个Tcl解决方案:

set fid [open file2 r]
set patterns [lmap line [split [read -nonewline $fid] \n] {string trim $line}]
close $fid

set fid [open file1 r]
set lines [split [read -nonewline $fid] \n]
close $fid

set wanted [lsearch -inline -all -regexp -not $lines [join $patterns "|"]]
puts [join $wanted \n]
This is ECO_01  
This is ECO_03  

参考:lsearch man page