当字符串使用awk或sed具有一定长度时,请删除行

当字符串使用awk或sed具有一定长度时,请删除行,awk,sed,Awk,Sed,我有一个包含4行的块的文件,它们属于一起。结构看起来像这样 @A1 ABCGKJTGE + A4 @B1 ACDFS + B4 @C1 SFDGDGDAD + C4 @A1 ABCGKJTGE + A4 @C1 SFDGDGDAD + C4 @A1 ABCGKJTGE + A4 @C1 SFDGDGDAD + C4 现在,当每个块的第二行的字符串长度不等于9时,我希望删除4的块。在这种情况下,“B块”将被删除。所以我的输出文件看起来像这样 @A1 ABCGKJTGE + A4 @B1 AC

我有一个包含4行的块的文件,它们属于一起。结构看起来像这样

@A1
ABCGKJTGE
+
A4
@B1
ACDFS
+
B4
@C1
SFDGDGDAD
+
C4
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4
现在,当每个块的第二行的字符串长度不等于9时,我希望删除4的块。在这种情况下,“B块”将被删除。所以我的输出文件看起来像这样

@A1
ABCGKJTGE
+
A4
@B1
ACDFS
+
B4
@C1
SFDGDGDAD
+
C4
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4

我会使用“awk”来执行此操作,但不确定在这种情况下如何执行此操作。

此awk cmd执行以下操作:

 awk '{a[NR]=$0}
    END{for(i=2;i<=NR;i+=4)
            if(length(a[i])==9)
                p[i-1]=p[i]=p[i+1]=p[i+2]=1
        for(x=1;x<=NR;x++)
                if(p[x])print a[x]}' file
awk'{a[NR]=$0}

END{for(i=2;i此awk cmd执行以下任务:

 awk '{a[NR]=$0}
    END{for(i=2;i<=NR;i+=4)
            if(length(a[i])==9)
                p[i-1]=p[i]=p[i+1]=p[i+2]=1
        for(x=1;x<=NR;x++)
                if(p[x])print a[x]}' file
awk'{a[NR]=$0}
结束{for(i=2;i
输出

@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
这里一个棘手的部分是
arr[NR%4]
引用
arr[0]
。因此我们必须在
print
语句中从“逻辑的”
arr[4]
更改为
arr[0]

如果每个“记录”的行数超过4行,则可以参数化该值,然后使用它驱动
for
循环以打印保存的记录,即

 for (i=1; i<=recSize; i++) {
   print arr[i]
 }
 print arr[0]
(i=1;i)的

输出

@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
这里一个棘手的部分是
arr[NR%4]
引用
arr[0]
。因此我们必须在
print
语句中从“逻辑的”
arr[4]
更改为
arr[0]

如果每个“记录”的行数超过4行,则可以参数化该值,然后使用它驱动
for
循环以打印保存的记录,即

 for (i=1; i<=recSize; i++) {
   print arr[i]
 }
 print arr[0]

for(i=1;i这里有一个
sed
解决方案:

sed -E 'N;N;N;/.*\n[^\n]{9}\n.*\n/ !d' test.txt
$ cat > yetanother.awk
{
    a=a $0 ORS                       # thanks @Ed Morton
}
NR%4==0 {                            # for every 4th record
    split(a,b,ORS)                   # split gathered a to b
    if(length(b[2]==9))              # if the second record in block
        printf "%s", a                # print it
    a=""                             # reset a
}
(根据您的操作系统,
-E
可能需要改为
-r
。)

这应该理解为“当你找到一行时,再读三行(总共四行),寻找第二行正好有9个字符长,如果没有找到,则删除所有四行。”

对于包含此内容的
test.txt

@A1
ABCGKJTGE
+
A4
@B1
ACDFS
+
B4
@C1
SFDGDGDAD
+
C4
输出为:


下面是一个
sed
解决方案:

sed -E 'N;N;N;/.*\n[^\n]{9}\n.*\n/ !d' test.txt
$ cat > yetanother.awk
{
    a=a $0 ORS                       # thanks @Ed Morton
}
NR%4==0 {                            # for every 4th record
    split(a,b,ORS)                   # split gathered a to b
    if(length(b[2]==9))              # if the second record in block
        printf "%s", a                # print it
    a=""                             # reset a
}
(根据您的操作系统,
-E
可能需要改为
-r
。)

这应该理解为“当你找到一行时,再读三行(总共四行),寻找第二行正好有9个字符长,如果没有找到,则删除所有四行。”

对于包含此内容的
test.txt

@A1
ABCGKJTGE
+
A4
@B1
ACDFS
+
B4
@C1
SFDGDGDAD
+
C4
输出为:


另一个受先前解决方案启发的AWK解决方案:

sed -E 'N;N;N;/.*\n[^\n]{9}\n.*\n/ !d' test.txt
$ cat > yetanother.awk
{
    a=a $0 ORS                       # thanks @Ed Morton
}
NR%4==0 {                            # for every 4th record
    split(a,b,ORS)                   # split gathered a to b
    if(length(b[2]==9))              # if the second record in block
        printf "%s", a                # print it
    a=""                             # reset a
}
并对其进行测试:

$ awk -f yetanother.awk structure.txt
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4

另一个受先前解决方案启发的AWK解决方案:

sed -E 'N;N;N;/.*\n[^\n]{9}\n.*\n/ !d' test.txt
$ cat > yetanother.awk
{
    a=a $0 ORS                       # thanks @Ed Morton
}
NR%4==0 {                            # for every 4th record
    split(a,b,ORS)                   # split gathered a to b
    if(length(b[2]==9))              # if the second record in block
        printf "%s", a                # print it
    a=""                             # reset a
}
并对其进行测试:

$ awk -f yetanother.awk structure.txt
@A1
ABCGKJTGE
+
A4
@C1
SFDGDGDAD
+
C4

使用gnu awk多行记录

awk '
BEGIN{ RS="(^|\n)@[^\n]*\n" }
length($1) == 9 {printf("%s%s", prt, $0)}
{prt=RT}
'

使用gnu awk多行记录

awk '
BEGIN{ RS="(^|\n)@[^\n]*\n" }
length($1) == 9 {printf("%s%s", prt, $0)}
{prt=RT}
'
解决方案:

运行:

$txr data.txr data @A1 ABCGKJTGE + A4 @C1 SFDGDGDAD + 补体第四成份 解决方案:

运行:

$txr data.txr data @A1 ABCGKJTGE + A4 @C1 SFDGDGDAD + 补体第四成份
@劳雷尔:不,这实际上是随机文本。我会对原始帖子做一些修改,以更好地反映情况。你如何判断它是分隔符还是行?@劳雷尔:我不确定我是否理解你的意思,但每行末尾都有一个行尾字符。因此在本例中,文件包含12行,输出文件sh我的意思是
A1
A2
,等等。我的意思是
ABCGKJTGE
之类的东西。我总是发现更容易理解积极编写的需求,而不是消极编写的需求。每个命令一开始都没有输出,所以在开始需求时说你想从中删除某些东西不会产生任何效果有意义。我不想说
,而是想删除包含非(负)第二行的(负)块9个字符长
,可以将其视为
。我想打印包含第二行的块,长度为9个字符
。没有双负数,因此更易于理解。只需说明要输出的内容,而不是与输入相比所做的更改。@Laurel:不,这实际上是随机文本。我将对为了更好地反映这种情况,你如何判断它是分隔符还是线条?@Laurel:我不确定我是否理解你的意思,但每行的末尾都有一个行尾字符。因此在这里的示例中,文件包含12行,输出文件应该包含8行,我的意思是
A1
A2
,等等。By分隔符我指的是
ABCGKJTGE
之类的东西。我总是发现更容易理解积极编写的需求,而不是消极编写的需求。每个命令一开始都没有输出,所以说你想从中删除一些东西来启动你的需求是没有意义的。与其说
我想删除(消极)包含非(负数)9个字符长的第二行的块
,将其视为
。我想打印包含9个字符长的第二行的块
。无双负数,因此更易于理解。只需说明要输出的内容,而不是与输入相比所产生的更改。