如何从另一个文件中删除具有匹配模式的行?
How to delete line with matching pattern from another file?
我想删除 FILE1 中包含 FILE2 中模式的行。
我如何使用 shell/bash 或 Tcl 执行此操作?
例如:
文件 1:
This is ECO_01
This is ECO_02
This is ECO_03
This is ECO_04
文件 2:
ECO_02
ECO_04
输出:
This is ECO_01
This is ECO_03
最通用的解决方案是
$ grep -vf file2 file1
请注意,任何字段上的任何子字符串匹配都将被计算在内。如果你只限制精确匹配到一个精确的字段(这里假设最后一个)
$ awk 'NR==FNR{a[]; next} !($NF in a)' file2 file1
你只需要使用 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
在 Tcl 中,您将加载模式文件并使用它们进行过滤。保持主要过滤流程从标准输入到标准输出可能是最简单的;您可以很容易地重定向那些 from/to 文件。由于您似乎想使用“is pattern a substring of”作为匹配规则,您可以使用 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
另一种 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
我想删除 FILE1 中包含 FILE2 中模式的行。
我如何使用 shell/bash 或 Tcl 执行此操作?
例如:
文件 1:
This is ECO_01
This is ECO_02
This is ECO_03
This is ECO_04
文件 2:
ECO_02
ECO_04
输出:
This is ECO_01
This is ECO_03
最通用的解决方案是
$ grep -vf file2 file1
请注意,任何字段上的任何子字符串匹配都将被计算在内。如果你只限制精确匹配到一个精确的字段(这里假设最后一个)
$ awk 'NR==FNR{a[]; next} !($NF in a)' file2 file1
你只需要使用 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
在 Tcl 中,您将加载模式文件并使用它们进行过滤。保持主要过滤流程从标准输入到标准输出可能是最简单的;您可以很容易地重定向那些 from/to 文件。由于您似乎想使用“is pattern a substring of”作为匹配规则,您可以使用 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
另一种 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