我有两个文件,一个是另一个的超集。我想从较大的文件中删除较小文件中的相同行。
一种可能的复杂情况是这些行包含反斜杠。
我该怎么做呢?
答案1
这是我的片段:
remove_lines()
{
# remove lines from a file
#
# $1 - source file with patterns of lines to be removed
# $2 - destination file
tmpfile=$(mktemp "$(dirname -- "$2")"/XXXXXXXX) &&
grep -F -f "$1" -v -- "$2" >>"$tmpfile" &&
mv -- "$tmpfile" "$2" &&
}
编辑:我刚刚意识到其中没有sed
,但这并不重要,不是吗?
答案2
@rajish 的答案grep
很接近,但忽略了一些东西:关于删除相同内容的问题线。默认情况下,grep
会匹配字符串(部分线条)。
POSIX grep有一个合适的选择:
-x
仅考虑使用行中除终止符之外的所有字符的输入行新队匹配整个固定字符串或正则表达式作为匹配行。
鉴于此,人们可以grep
这样做:
cp -f -p input.txt input.txt~
grep -v -x -F -f input.pat input.txt~ >input.txt
在哪里输入.pat包含要删除的行,并且输入.txt是要更新的文件。
@nvarun 的解决方案使用 sed
除了不转义/
模式文件中的字符之外,还有类似的问题。这个例子对我有用,并将语法限制为POSIX sed:
cp -f -p input.txt input.txt~
sed -e 's/\([\/]\)/\\\1/g' -e 's/^/\/^/' -e 's/$/$\/d/' input.pat > input.sed
sed -f input.sed input.txt~ >input.txt
为了整洁起见,两者都在更新之前保存原始文件(POSIX cp)。
输入.pat
first
this is second
second/third
second\third
输入.txt
first
only first should match
this is not first
this is second
the previous line said this is second
first/second/third
second/third
first\second\third
second\third
结果:
only first should match
this is not first
the previous line said this is second
first/second/third
first\second\third
答案3
尝试以下脚本;
## $1 - Small File
## $2 - Large File
sed 's/^/\//; s/$/\/d/; s/\\/\\\\/g' $1 > $HOME/sed_scpt.txt
sed 's/\\/\\\\/g' $2 | sed -f $HOME/sed_scpt.txt > $HOME/desired_output.txt
## Alternatively, you could change the 2nd line with the following;
sed -f $HOME/sed_scpt.txt $2 > $HOME/desired_output.txt
注意:我使用过 GNU sed 4.2.1。