删除具有匹配项的单词,但将原始单词保留在文件中

时间:2019-06-07 06:30:44

标签: shell awk sed

我正在努力实现以下目标:

有一个包含多个单词的文件,例如:

示例txt的输出为

testStr
testmystring
testmystring_1
testmystringwq
testStr_3
testStrasd
testStr-345
testStr1
testingStr1

现在我要实现的是,如果我逐行操作文件,即第一次使用testStr,那么应该删除所有从testStr开头的单词,但在这里应该保留testStr。

预期输出为

testStr
testmystring
testmystring_1
testmystringwq
testingStr1

现在应该比较文件中的下一个字符串,即testmystring。然后预期的输出是

testStr
testmystring
testingStr1

依此类推...

我尝试使用sed命令通过模式进行删除,并且可以正常工作。但是我需要将原始模式保留在文件中。

sed -i '/testStr*/d' ./sample txt 

3 个答案:

答案 0 :(得分:1)

这可能对您有用(GNU sed):

sed 's/\<\(testStr\)\S*/\1/;H;$!d;x;s/.//;:a;s/\<\(\(testStr\n\).*\)\2/\1/;ta' file

删除字符串testStr之后的所有字符。将结果和不变的行存储在保留空间中。在文件末尾,删除引入的换行符,然后删除字符串testStr以外的所有字符串。

一个更简单的解决方案可能是:

sed 's/\<\(testStr\)\S*/\1/' file | sort -u

但是,这将删除除testStr以外的其他行的重复项,并且还可能更改原始顺序。

编辑:为了适应对原始问题的更改,提供了两个文件。第一个原始文件包含要测试的字符串(file),新的第二个文件仅包含要匹配的字符串(fileInput)。

使用上述解决方案和替代方法,从fileInput构建脚本:

sed 'H;$!d;x;s/.//;s/\n/|/g;s#.*#s/\\<(&)\\S*/\\1/;H;$!d;x;s/.//;:a;s/\\<(((&)\\n).*)\\2/\\1/;ta#' fileInput |
sed -Ef - file

答案 1 :(得分:0)

那呢?

$ grep -Evf <(sed 's/^/^/; s/$/.+/' sample.txt) sample.txt
testStr
testmystring
testingStr1

(需要bash,zsh,ksh93或其他能够理解<(command)样式重定向的shell。)

答案 2 :(得分:0)

这是如何使用文字字符串执行的操作:

$ awk 'NR==FNR{tgts[$0]; next} {for (tgt in tgts) if (($0 != tgt) && (index($0,tgt) == 1)) next} 1' targets file
testStr
testmystring
testingStr1

以上内容在这些输入文件上运行:

$ tail -n +0 targets file
==> targets <==
testStr
testmystring

==> file <==
testStr
testmystring
testmystring_1
testmystringwq
testStr_3
testStrasd
testStr-345
testStr1
testingStr1

无论哪个文件中包含什么字符,以上内容都将起作用。