我正在使用打印这些行的awk命令(someawkcommand)(awkoutput):
>Genome1
ATGCAAAAG
CAATAA
然后,我想使用此输出(awkoutput)作为sed命令的输入。这样的事情:
someawkcommand | sed 's/awkoutput//g' file1.txt > results.txt
file1.txt:
>Genome1
ATGCAAAAG
CAATAA
>Genome2
ATGAAAAA
AAAAAAAA
CAA
>Genome3
ACCC
最终目标是删除包含awk先前找到的确切模式的文件(file1.txt
)中的所有行。
文件results.txt
包含(sed的输出):
>Genome2
ATGAAAAA
AAAAAAAA
CAA
>Genome3
ACCC
我该如何编写sed命令?是否有任何简单的方法可以将awk的输出识别为输入?
答案 0 :(得分:1)
将GNU awk用于多字符RS:
$ cat file1
>Genome1
ATGCAAAAG
CAATAA
$ cat file2
>Genome1
ATGCAAAAG
CAATAA
>Genome2
ATGAAAAA
AAAAAAAA
CAA
>Genome3
ACCC
$ gawk -v RS='^$' -v ORS= 'NR==FNR{rmv=$0;next} {sub(rmv,"")} 1' file1 file2
>Genome2
ATGAAAAA
AAAAAAAA
CAA
>Genome3
ACCC
对于新手来说可能不明显的东西,但是非常常见的awk习语:
-v RS='^$'
告诉awk将整个文件读作一个字符串(而不是一次默认的一行)。-v ORS=
将输出记录分隔符设置为空字符串(而不是它的默认换行符),这样当文件作为字符串打印时,awk不会在其后添加换行符。NR==FNR
是仅对第一个输入文件为真的条件。1
是一个调用打印当前记录的默认操作的真实条件。答案 1 :(得分:0)
这是一个可能的sed
解决方案:
someawkcommand | sed -n 's_.*_/&/d;_;H;${x;s_\n__g p}' | sed -f - file1.txt
第一个sed
命令将someawkcommand
的输出转换为sed
表达式。
具体而言,它会变成
>Genome1
ATGCAAAAG
CAATAA
成:
/>Genome1/d;/ATGCAAAAG/d;/CAATAA/d;
(使用sed
语言:删除包含这些模式的行;请注意您必须转义/
,[
,]
,*
,{ {1}},^
输出中的$
,如果有的话,还有其他替代例。)
第二个awk
命令将其作为输入表达式读取(sed
从文件-f -
读取sed
个命令,即从管道获取命令)并应用于文件{{1} }。
其他读者备注:
OP希望使用-
,但正如评论中所述,它可能不是解决此问题的最简单方法。删除file1.txt
行可能更简单。另一个(简单)解决方案可能是使用sed
与awk
(反向匹配)和grep
(从文件中读取模式)选项,这样:
-v
编辑:关注@ rici的评论,这是一个新命令,它将-f
的输出作为单个多线模式。
免责声明:它变脏了。孩子们,不要回家。强烈建议成年人考虑避免someawkcommand | grep -v -f - file1.txt
。
awk
内部sed
的输出是:
someawkcommand | \
sed -n 'H;${x;s_\n__;s_\n_\\n_g;s_.*_H;${x;s/\\n//;s/&//g p}_ p}' | \
sed -n -f - file1.txt
附加缺点:它会添加一个空行而不是删除模式。无法轻松修复(如果模式位于文件的开头/结尾,则会出现问题)。如果您真的愿意,请添加替换以将其删除。
答案 2 :(得分:0)
这可以更容易地在awk中完成,但通常"消除重复"代码不正确。据我所知,目标是从文件中删除整个节。
这是一个可能的解决方案,假设第一个awk脚本输出单个节:
awk 'NR == FNR {stanza[nstanza++] = $0; next}
$0 == stanza[i] {++i; next}
/^>/ && i == nstanza {i=0; next}
i {for (j=0; j<i; ++j) print stanza[j]; i=0}
{print $0;}
' <(someawkcommand) file1.txt
答案 3 :(得分:0)
这可能适合你(GNU sed):
sed '1{h;s/.*/:a;$!{N;ba}/p;d};/^>/!{H;$!d};x;s/\n/\\n/g;s|.*|s/&\\n*//g|p;$s|.*|s/\\n*$//|p;x;h;d' file1
sed -f - file2
这将从file1构建一个脚本,然后针对file2运行它。
脚本在file2中徘徊,然后使用file1的内容进行gobal替换。最后,它删除了内容删除导致的结束文件中的任何空行。
要查看从file1生成的脚本,请删除管道和第二个sed命令。
另一种方法是使用diff和sed:
diff -e file2 file1 | sed 's/d/p/g' | sed -nf - file2