当--AnchorABC
可以重复1-N时如何获得--AnchorABC
和--Anchor<not ABC>
之间的内容的任何想法?
示例输入:
It
is
a
lovely
day
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
--AnchorXYZ
I
am
fine
--AnchorLMN
示例输出(删除最后一行并不重要(:
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
--AnchorXYZ
如果有偶数--AnchorABC
的数量,则很容易(尽管hacky(,但是有一个奇数,那么hack会分解。使用SED,我试图在--AnchorABC
和以--
开头但不是的范围内的线之间进行模式范围,但是SED没有负面的lookahead。
基本上问题语句是:在第一次出现以--
开头的模式之间,在--
之后的键,然后是任意结局,然后是一个以模式--
开头的行,但以一个键,但以一个键不同的键。或另一种方式:
- 匹配
--AnchorABC
- 如果后续行与
--AnchorABC
匹配或不以--
开头的任何东西,请打印 - 如果一条线与
--Anchor
匹配,但不是--AnchorABC
,请停止
- 如果后续行与
编辑:清楚地表明,第二个锚键尚不清楚,并且"键"可以是多个字符。
使用awk:
awk '/^--AnchorA/{l=1} /^--Anchor[^A]/{l=0; print; exit}l' file.txt
或更简单,感谢@iamuser的想法:
awk '/^--AnchorA/{l=1}; l; /^--Anchor[^A]/{exit}' file.txt
说明:
-
//{}
=正则条件和执行 - 因此,
/^--AnchorA/{l=1}
表示分配l=1
如果正则匹配 - 中间的
l
是一个尴尬的技巧:它表示true
,在真实条件下,awk默认值是打印。 - 第二个
//{}
的同一件事,但我们使用负范围排除字符A
当l = 1在stdout上打印1时,当l = 0时,它不是
如果您不需要否定字符,而是字符串
然后,佩尔(Perl
perl -ne 'print if /^--AnchorA/ .. /^--Anchor(?!A)/' file.txt
检查环顾四周(您可以用字符串替换A
,而不仅仅是字符(
或保持尴尬:
awk '
/^--AnchorA/{l=1;print;next};
l;
/^--Anchor/ && $0 !~ /^--AnchorABC/ {exit}
' file.txt
sed用于单个行上的简单替换,即全部。对于其他任何东西,您应该使用尴尬:
$ awk '/^--/{f=/--AnchorABC/} f' file
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
也可以调整打印终止的非匹配线,但您说having the last line deleted isn't super important
,所以我没有打扰。
说明:
-
/^--/{f=/--AnchorABC/}
=当前行以--
开头时,如果该行包含--AnchorABC
和0
,则将标志f
设置为1
,否则。 -
f
在末尾=如果将标志f
设置为1
,则agk发生默认操作是要打印当前行。
我想出了一个令人讨厌的SED解决方案,尽管我更喜欢Gilles的尴尬解决方案来可读性:
sed -ne "/^--AnchorA/{p;
:loop
n;
p;
/^--/{/^--AnchorA/!q};
b loop}" testfile | sed '$d'
这可能对您有用(gnu sed(:
sed -nr '/^--AnchorABC/{:a;N;/^--AnchorABC[^n]*'''/Mba;/^--Anchor[^n]*'''/M!ba;p}' file
使用的gnu seds多行式串联'
(此处显示为'''
,因为该命令是单个引用的(。这使用N
来收集多行,如果附加的最后一行是--AnchorABC
继续附加到开始--Anchor
的行,并且不继续ABC
,则打印收集并重复。
n.b。SEDS M
标志允许^
和'
分别匹配一条线的开始和模式空间的末端。
这是awk
解决方案,
$ awk '/AnchorA/{a=1};a;/AnchorB/{exit}' file
这是sed
解决方案,
$ sed '/AnchorA/,/AnchorB/!d;/AnchorB/q' file
输出(在两种情况下(:
--AnchorA something
--AnchorA something else
--AnchorA yet something else
Hey
how
are
you
--AnchorB
awk -v search="AnchorABC" '
BEGIN{r="^[-]+"search}
$0~r{f=1}f;
/^[-]+/ && $0 !~ r{exit}
' file
测试结果:
输入:
$ cat file
It
is
a
lovely
day
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
--AnchorXYZ
I
am
fine
--AnchorLMN
输出:
$ awk -v search="AnchorABC" 'BEGIN{r="^[-]+"search}$0~r{f=1}f;/^[-]+/ && $0 !~ r{exit}' file
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
--AnchorXYZ
解决方案将grep
和sed
与>负LookAhead :
$ A=$(grep -Pnm1 '^--AnchorABC' input.file | cut -d':' -f1); B=$(tail -n +$A input.file |grep -Pnm1 '^--Anchor(?!ABC)' | cut -d':' -f1); sed -n "$A,+$((B-1)) p" input.file
--AnchorABC something
--AnchorABC something else
--AnchorABC yet something else
Hey
how
are
you
--AnchorXYZ
说明:
-
$(grep -Pnm1 '^--AnchorABC' input.file | cut -d':' -f1)
查找--AnchorABC
的第一次出现的行号 -
$(tail -n +$A input.file |grep -Pnm1 '^--Anchor(?!ABC)' | cut -d':' -f1)
从第一次出现中,您可以找到多少行,直到达到符合'^--Anchor(?!ABC)'
条件的线,并且您相对于'^--AnchorABC'
的第一次出现
相对获得其线号。 - 您仅用
sed -n "$A,+$((B-1)) p" input.file
打印所讨论的范围