【问题标题】:Sed. How to remove line match with pattern and strings arround it?赛德。如何删除带有模式和字符串的行匹配?
【发布时间】:2015-01-19 15:10:10
【问题描述】:

我有一个文件,您要在其中删除按模式匹配的行并删除上面和下面的字符串。

举例:

FFFFIFIBBFFFFFFFFFFFFFBBBBFBBBBFBBBB77<<BBBBBB7B<BBBBBB<B< @HISEQ:102:h9u5badxx:1:1101:13002:2147 1:N:0:CTGT GATCCCCGTCTATCAGATACACGTTACTCAGCTAGTGCGAATGCGAACGCGAAATTTT + FFFFFFFFBBFFFFFFFFFFFFFBFBFFFFFFFFFBFFFBFFFFFBFFFFFFFFFBFB @HISEQ:102:h9u5badxx:1:1101:15368:2194 1:N:0:CTGT + FFIFBFFIFFBBBFFFFFFFBBFFBFFBBBFFFBB7BBBBBBFFFBB700<7770<BBB0<0<BFFBFBFFFFF @HISEQ:102:h9u5badxx:1:1101:19167:2169 1:N:0:CTGT GATCTCATATAGGGCAGCGTGGTCGCGGC

我想删除不包含核苷酸序列的第二个块。

最终结果:

`FFFFIFIBBFFFFFFFFFFFFFBBBBFBBBBFBBBB77<<BBBBBB7B<BBBBBB<B<
@HISEQ:102:h9u5badxx:1:1101:13002:2147 1:N:0:CTGT
GATCCCCGTCTATCAGATACACGTTACTCAGCTAGTGCGAATGCGAACGCGAAATTTT
+
FFIFBFFIFFBBBFFFFFFFBBFFBFFBBBFFFBB7BBBBBBFFFBB700<7770<BBB0<0<BFFBFBFFFFF
@HISEQ:102:h9u5badxx:1:1101:19167:2169 1:N:0:CTGT
GATCTCATATAGGGCAGCGTGGTCGCGGC
`

与此块匹配的模式

'^.+$(\n)^(@HISEQ).*$(\n)^\+'

适用于 perljavascript,但不适用于 sed

因为 sed 不适用于换行符。

我找到了解决办法

sed -e ':a;N;$!ba;s/\n/ /' test

但是此代码将换行符替换为空格。如果在此代码中插入我的正则表达式:

sed -e ':a;N;$!ba;/^.+$(\n)^(@HISEQ).*$(\n)^\+/d' test

这不起作用。 你能帮我找到这个问题的解决方案吗?


我只是愚蠢。我误解了文件格式。 输入:

@HWI-ST383:199:D1L73ACXX:3:1101:1309:1956 1:N:0:ACAGTGA 
+ 
JJJHIIJFIJJJJ=BFFFFFEEEEEEDDDDDDDDDDBD 
@HWI-ST383:199:D1L73ACXX:3:1101:3437:1952 1:N:0:ACAGTGA
GATCTCGAAGCAAGAGTACGACGAGTCGGGCCCCTCCA 
+ 
IIIIFFF<?6?FAFEC@=C@1AE############### 

如何编辑常规 exp 以获得你想要的

输出:

@HWI-ST383:199:D1L73ACXX:3:1101:3437:1952 1:N:0:ACAGTGA
GATCTCGAAGCAAGAGTACGACGAGTCGGGCCCCTCCA 
+ 
IIIIFFF<?6?FAFEC@=C@1AE###############

【问题讨论】:

  • sed 一次处理一行。使用awkperl 可能会更好,这样可以更轻松地处理更大的块。
  • “将插入符号替换为空格”是什么意思?您的文件中没有插入符号。
  • 对不起我的英语。我的意思是换行符,而不是插入符号
  • 不使用修饰符的更好的正则表达式是.+$\r?\n@HISEQ.*$\r?\n\+\s*
  • awk 这对我来说太难了。我不明白 awk 的逻辑。

标签: regex bash sed


【解决方案1】:

如果我理解正确,那么

sed ':loop; N; /\n+/ ! { $ ! b loop }; /\n@HISEQ[^\n]\+\n+/ d' foo.txt

会起作用。如下:

:loop                    # in a loop
N                        # fetch more lines
/\n+/ ! { $ ! b loop }   # until one starts with + or is the last line
/\n@HISEQ[^\n]\+\n+/ d   # if the penultimate line of all that begins with @HISEQ,
                         # discard the lot.

最后一个模式使用了这样一个事实,即在找到以+ 开头的第一行之后立即对其进行检查,因此它末尾的\n+ 唯一地匹配块中最后一行的开头。

【讨论】:

  • 你是个魔术师!这就是你需要的!你能告诉我在哪里可以阅读 sed 中的循环和循环
  • 每当我需要查找 sed 的东西时,我都会去here
  • 我还在仔细看这个……哈!..+1
【解决方案2】:

要删除第二个块,您可以这样做:

awk 'NR!=2' RS=+ ORS=+ input

但我怀疑你想要的更像是:

awk '/[GATC]{5,}\n/' RS=+ ORS=+ input

awk '/\n[GATC]*\n/' RS=+ ORS=+ input

【讨论】:

  • RS=+ 表示记录分隔符是字符+。我假设您对 + 作为 RE 元字符感到困惑,但在这种情况下并非如此(即,当它是字符串中的第一个字符时)。
  • 另外,请注意,对于 RS 使用任何超过一个字符的字符串都不是标准的 awk。 gnu awk 允许 RS 成为任意正则表达式(我认为),但是使用长度超过一个字符的字符串由语言本身未定义(大多数实现要么将其视为正则表达式,要么将其截断并仅使用第一个字符。)
【解决方案3】:

使用awk 更容易进行此解析:

awk -v RS=+ -v ORS=+ '!/\n@HISEQ[^\n]*\n$/' file
FFFFIFIBBFFFFFFFFFFFFFBBBBFBBBBFBBBB77<<BBBBBB7B<BBBBBB<B<7BBBBFFFBBBBFBBBBBBBFBFFFFB<<
@HISEQ:102:h9u5badxx:1:1101:13002:2147 1:N:0:CTGT
GATCCCCGTCTATCAGATACACGTTACTCAGCTAGTGCGAATGCGAACGCGAAATTTT
+
FFIFBFFIFFBBBFFFFFFFBBFFBFFBBBFFFBB7BBBBBBFFFBB700<7770<BBB0<0<BFFBFBFFFFF<B<7<<BBBBFB0
@HISEQ:102:h9u5badxx:1:1101:19167:2169 1:N:0:CTGT
GATCTCATATAGGGCAGCGTGGTCGCGGC
+

【讨论】:

    【解决方案4】:
     sed '/FFFFFFFFBBFFFFFFFFFFFFFBFBFFFFFFFFFBFFFBFFFFFBFFFFFFFFFBFB/,/\+/ d' YourFile
    

    应该够了

    【讨论】:

    • 行范围删除...+1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多