Bash 用贪婪的正则表达式痛击sed
我有一个GTF文件(TSV类型),其结构如下:Bash 用贪婪的正则表达式痛击sed,bash,Bash,我有一个GTF文件(TSV类型),其结构如下: ENST00000488147.1|ENSG00000227232.5|OTTHUMG00000000958.1|OTTHUMT00000002839.1|WASH7P-201|WASH7P|1351|unprocessed_pseudogene| 13511132.24 244.489 2.7098 ENST00000619216.1|ENSG00000278267.1|-|-|MIR6859-1-201|MIR6859-1|68|miRN
ENST00000488147.1|ENSG00000227232.5|OTTHUMG00000000958.1|OTTHUMT00000002839.1|WASH7P-201|WASH7P|1351|unprocessed_pseudogene| 13511132.24 244.489 2.7098
ENST00000619216.1|ENSG00000278267.1|-|-|MIR6859-1-201|MIR6859-1|68|miRNA| 68 26.127 0 0
ENST00000473358.1|ENSG00000243485.5|OTTHUMG00000000959.2|OTTHUMT00000002840.1|MIR1302-2HG-202|MIR1302-2HG|712|lncRNA| 712 493.243 0 0
我想删除第一列中的所有名称,但第一列中的名称由“|”分隔。例如,第一行应该是:
ENST00000488147.1 13511132.24 244.489 2.7098
我的想法是用“\t”替换从第一个“|”到第一个“\t”的所有内容,但是sed让我失望了。此命令不进行任何更改:
sed 's/|*\t/\t/' test.tsv
我做错了什么?有没有更好的方法可以完全做到这一点?考虑一下:
sed -re $'s@[|][^\t]*\t@\t@g'
- 使用
是一种ksh/bash语法扩展,它使$'…'
通过shell扩展为文本选项卡,而不是假设您有一个$'\t'
,它(不参考标准)将sed
序列视为选项卡\t
将sed-r
置于POSIX ERE模式,而不是BRE模式sed
- 使用
只匹配文本[|]
字符,而不管使用哪个正则表达式语法变量 - 使用
匹配零个或多个非制表符的内容,而[^\t]*
将匹配制表符的内容,这不会产生所需的输出*
在上下文中,作为可测试代码:
write_line() {
printf '%s\t' "$@" && printf '\n';
}
generate_input() {
write_line 'ENST00000488147.1|ENSG00000227232.5|OTTHUMG00000000958.1|OTTHUMT00000002839.1|WASH7P-201|WASH7P|1351|unprocessed_pseudogene|' 13511132.24 244.489 2.7098
write_line 'ENST00000619216.1|ENSG00000278267.1|-|-|MIR6859-1-201|MIR6859-1|68|miRNA|' 68 26.127 0 0
write_line 'ENST00000473358.1|ENSG00000243485.5|OTTHUMG00000000959.2|OTTHUMT00000002840.1|MIR1302-2HG-202|MIR1302-2HG|712|lncRNA|' 712 493.243 0 0
}
generate_input | sed -re $'s@[|][^\t]*\t@\t@g'
…产生:
ENST0000488147.1 13511132.24 244.489 2.7098
ENST0000619216.1 68 26.127 0 0
ENST0000473358.1 712 493.243 0
考虑:
sed -re $'s@[|][^\t]*\t@\t@g'
- 使用
是一种ksh/bash语法扩展,它使$'…'
通过shell扩展为文本选项卡,而不是假设您有一个$'\t'
,它(不参考标准)将sed
序列视为选项卡\t
将sed-r
置于POSIX ERE模式,而不是BRE模式sed
- 使用
只匹配文本[|]
字符,而不管使用哪个正则表达式语法变量 - 使用
匹配零个或多个非制表符的内容,而[^\t]*
将匹配制表符的内容,这不会产生所需的输出*
在上下文中,作为可测试代码:
write_line() {
printf '%s\t' "$@" && printf '\n';
}
generate_input() {
write_line 'ENST00000488147.1|ENSG00000227232.5|OTTHUMG00000000958.1|OTTHUMT00000002839.1|WASH7P-201|WASH7P|1351|unprocessed_pseudogene|' 13511132.24 244.489 2.7098
write_line 'ENST00000619216.1|ENSG00000278267.1|-|-|MIR6859-1-201|MIR6859-1|68|miRNA|' 68 26.127 0 0
write_line 'ENST00000473358.1|ENSG00000243485.5|OTTHUMG00000000959.2|OTTHUMT00000002840.1|MIR1302-2HG-202|MIR1302-2HG|712|lncRNA|' 712 493.243 0 0
}
generate_input | sed -re $'s@[|][^\t]*\t@\t@g'
…产生:
ENST0000488147.1 13511132.24 244.489 2.7098
ENST0000619216.1 68 26.127 0 0
ENST0000473358.1 712 493.243 0
\t
与POSIX BRE或ERE正则表达式语法规范都不兼容,指望
被解释为文本而不是“或”/“分支运算符会使代码变得脆弱(意味着如果解释为ERE它将失败)。此外,即使
是文本,*任何东西都将意味着“零个或多个管道,后跟任何内容”;*
只匹配它所后跟的零个或多个特定内容;它不匹配“任何内容”“,就像在fnmatch/glob样式的模式中一样,而不是在正则表达式中一样。@CharlesDuffy Wrt意味着如果解释为ERE,它将失败。您知道有任何这样做的实现吗?如果给定可选的-r
参数,许多实现将--意味着代码不能与其他实现组合,ERE具体做法。@oguzismail Re:\009
,据我所知,这是未定义的行为,因此平台将其视为字符序号是合法的,但不是必需的。\t
与POSIX BRE或ERE regex语法规范都不兼容,并且依赖于将
解释为文字而不是数字“或”/“分支运算符使代码变得脆弱(如果解释为ERE,则意味着它将失败)。此外,即使
是文本,*anything
将表示“零个或多个管道,后跟任何内容”;*
只匹配它所遵循的特定内容的零个或多个;它不匹配“任何内容”“,就像在fnmatch/glob样式的模式中一样,而不是在正则表达式中一样。@CharlesDuffy Wrt意味着如果解释为ERE,它将失败。您知道有任何这样做的实现吗?如果给定可选的-r
参数,许多实现将--意味着代码不能与其他实现组合,有一些具体的做法。@oguzismail Re:\009
,据我所知,这是未定义的行为,因此平台将其视为字符序号是合法的,但不是必需的。你简直太棒了!你简直太棒了!