[英]rename specific lines in a text file with sed
我有一个看起来像这样的文件:
>alks|keep1|aoiuor|lskdjf
ldkfj
alksj
asdflkj
>jhoj_kl|keep2|kjghoij|adfjl
aldskj
alskj
alsdkj
我想只编辑以>
开头的行,最好是就地编辑,以获取文件:
>keep1
ldkfj
alksj
asdflkj
>keep2
aldskj
alskj
alsdkj
我知道原则上这可以通过 sed/awk/cut 的各种组合来实现,但我一直无法找出正确的组合。 理想情况下它应该很快——文件有数百万行,而且许多行也很长。
关于我要编辑的行的关键内容:
>
开头|
(因此思考cut
会有所帮助(我的大多数 sed 尝试都是纯垃圾)
cut -d '|' -f 2 test.txt
得到我想要的字符串,它也保留其他行。 所以它很接近,但是(当然)它不会在cut
应用的行上保留初始>
,因此它缺少解决方案的关键部分。
使用sed
:
sed -E '/^>/ s/^[^|]+\|([^|]+).*/>\1/'
/^>/
到 select 以>
开头的行,对于给定的样本不是绝对必要的,但有时这比单独使用s
提供更快的结果^[^|]+\|
这将匹配非|
从行首开始的字符([^|]+)
捕获第二个字段.*
rest 的线>\1
替换字符串,其中\1
将具有([^|]+)
的内容如果您的输入只有 ASCII 字符,这将为您提供更快的结果:
LC_ALL=C sed -E '/^>/ s/^[^|]+\|([^|]+).*/>\1/'
定时
awk
更快,而mawk
甚至更快sed
解决方案对于实际数据更快使用您显示的示例,您可以简单地尝试以下操作。 在此代码中,我们将字段分隔符设置为|
对于 Input_file 的所有行,然后在主程序中检查行是否从>
开始,然后打印第二个字段,否则打印完整的行。
awk -F'|' '/^>/{print ">"$2;next} 1' Input_file
说明:为上述添加详细说明。
awk -F'|' ' ##Starting awk program from here and setting field separator as | here.
/^>/{ ##Checking condition if line starts from > then do following.
print ">"$2 ##Printing 2nd field of current line here.
next ##next will skip all further statements from here.
}
1 ##Will print current line.
' Input_file ##mentioning Input_file name here.
您还可以使用以下awk
命令:
awk -F\| '/^>/{print ">"$2} !/^>/{print}' file
# Inplace replacement with gawk (GNU awk)
gawk -i inplace -F\| '/^>/{print ">"$2} !/^>/{print}' file
# "Inline-like" replacement with any awk
awk -F\| '/^>/{print ">"$2} !/^>/{print}' file > tmp && mv tmp file
这里,
-F\|
- 将字段分隔符设置为|
字符/^>/
是条件:如果行以<
开头(而!/^>/
表示相反){print ">"$2}
打印字段 2 的值,并在其前面加上>
字符{print}
只是打印整行。 请注意,由于!/^>/{print}
可以简化为!/^>/
因为print
是默认操作。
查看在线演示:
s='>alks|keep1|aoiuor|lskdjf
ldkfj
alksj
asdflkj
>jhoj_kl|keep2|kjghoij|adfjl
aldskj
alskj
alsdkj'
awk -F\| '/^>/{print ">"$2} !/^>/{print}' <<< "$s"
Output:
>keep1
ldkfj
alksj
asdflkj
>keep2
aldskj
alskj
alsdkj
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.