Regex 如果遇到其他几个节头中的任何一个,如何退出Sed中的节模式匹配?

Regex 如果遇到其他几个节头中的任何一个,如何退出Sed中的节模式匹配?,regex,bash,sed,pattern-matching,editing,Regex,Bash,Sed,Pattern Matching,Editing,我正在使用sed内联编辑开放标准多节、空格分隔文件中特定节中的特定条目,该文件对某些数值常量进行编码 我有一个工作表达式来实现这一点,但我另外希望它在到达另一个节标题时能够退出,而没有找到与内部模式匹配的内容,因为根据标准,理论上这些节可能会出现故障,并且我要查找的标签/模式可能与文件的其他节匹配 文件规范的抽象版本以部分标题开始,标题作为标题关键字字符串列表,即平面,列车,汽车,总线``潜艇。要进行标识,标题关键字字符串必须位于行的开头,并且必须后跟空白字符(空格或制表符)。该行或下一行上可能

我正在使用
sed
内联编辑开放标准多节、空格分隔文件中特定节中的特定条目,该文件对某些数值常量进行编码

我有一个工作表达式来实现这一点,但我另外希望它在到达另一个节标题时能够退出,而没有找到与内部模式匹配的内容,因为根据标准,理论上这些节可能会出现故障,并且我要查找的标签/模式可能与文件的其他节匹配

文件规范的抽象版本以部分标题开始,标题作为标题关键字字符串列表,即
平面
列车
汽车
总线``潜艇
。要进行标识,标题关键字字符串必须位于行的开头,并且必须后跟空白字符(空格或制表符)。该行或下一行上可能会有其他空格分隔的特定于节的参数,尽管大多数节没有这些参数。空行被忽略,因此可用于提高可读性,但不能假设。在“!”之后有什么事吗或“*”假定为注释。在一个部分中,N个公共属性关键字(例如
小的
中的
大的
大的
)的某个给定组合的一组常量由后面的数字常量(例如
##########
)定义。属性关键字在多个节中使用,但不能保证在特定节中找到

例如:

*
* Header comments
*

PLANES
!
! COMMENTS
!
BIG MEDIUM ##.### ##.###
BIG SMALL ##.### ##.###
...
SMALL SMALL ##.### ##.###
THE_TRAINS
!
! COMMENTS
!
MEDIUM MEDIUM SMALL ##.### ##.### ! COMMENT STUFF
MEDIUM SMALL SMALL ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG ##.### ##.###



AN_AUTOMOBILE 0.1 shift red
!
! COMMENTS
SMALL SMALL SMALL SMALL ##.### ##.### ##.###
SMALL MEDIUM SMALL SMALL ##.### ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG SMALL ##.### ##.### ##.###

BUSES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
LARGE ##.### ##.### ## !
SUBMARINES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
HUGE ##.### ##.### ## !
*
之后的任何内容在文件标准中被视为注释

节是通过遇到后跟空格的关键字来定义的。在此之后,可能会有特定于节的填充变量(请参见编辑的示例中的
shift
),但最终每个节都有一个数字常量列表,前面有一组N个标识符,这些标识符对所有节都是通用的

节之间或节内各行之间的空白是任意的,可以添加以提高可读性,但不能假定

如果排序与我的当前文件相同,则模式为:

sed -i '/SUBMARINES/{:keep_reading;n; /^MEDIUM.*$/!bkeep_reading s/^MEDIUM.*$/DERP/ }' file.dat
…有效

如果上述表达式不清楚我的预期操作,我的目标是替换以某个给定关键字(即潜艇[\t]
)为首的小节中的某些模式(即
^MEDIUM.*$
)。在本例中,我只是将整个匹配线替换为
DERP
。在实际的实现中,我会做一个特定于实现的替换,但我已经知道如何做了,它的细节对于如何在sed中使用内置的微语言来尝试达到这一点是多余的,如果遇到其他子部分而在目标子部分中找不到匹配项,则退出

但是,如果部分出现故障,它可能会再次中断(即,如果我尝试替换
总线中的
巨型
,它将继续到下一小节,
潜艇
,并替换该小节,因为在给定部分中找不到该小节)

在遇到给定的章节标题关键字后加空格/制表符(即
潜艇[\t]
),如果我遇到任何其他章节标题/副标题(即
飞机
公共汽车
汽车
,以及
火车
),我该如何摆脱

这将防止在
潜艇
中替换以
巨型
开头的线路,而我的意图是仅在
总线
中找到以
巨型
开头的线路时才替换该线路


编辑1:

我想是这样的:

sed -i '/BUSES/{:keep_reading;n; /^HUGE.*$/!bkeep_reading /PLANES/\|/THE_TRAINS/\|/AN_AUTOMOBILE/\|/SUBMARINES/q s/^HUGE.*$/DERP/g }' file.dat
。。。可以工作,但该表达式给出了错误:

sed:-e表达式#1,字符60:未知命令:`'


编辑2:

我有一个半工作的解决方案:

sed -i '/BUSES/{:keep_reading;n; /^PLANES[ \t]\|^THE_TRAINS[ \t]\|^AN_AUTOMOBILE[ \t]\|^BUSES[ \t]/q; /^HUGE.*$/!bkeep_reading;  s/^HUGE.*$/DERP/g; }' file.dat
但我现在意识到,我以前的两种解决方案实际上都会在内联编辑时删除
maging
之后的任何行。我没有意识到这一点,因为我匹配的标签恰好是文件中的最后一行

上述模式正确退出,但会截断文件的其余部分。这似乎是一个简单的解决方案--如何保持文件的其余部分不变



另外,如果使用了这种附加语法,是否有更好的工具可以从命令行使用(例如perl、python等?

地址范围:

sed -i '/^SUB_HEADING_II$/,/^[A-Z_]\+$/{ s/^LBL_B1.*$/DERP/g }' file
替换将应用于
子标题_II
和下一行(包含大写字符和下划线的混合)之间的行。

在查找by之后的 如果要将以
LBL\u B1
开头的行更改为以
SUB\u HEADING\u II
SUB\u HEADING\u IV
(但不是
SUB\u HEADING\u III
)开头的块中的
DERP
,则在任何版本的
sed
中都可以执行此操作(尽管它不会覆盖原始文件):

对于子目
II
IV
(我使用了符号的重合紧凑性)至空行(或EOF)范围内的行,用
DERP
替换行开头的
LBL_B1

如果副标题更加多样化,则:

sed -e '/^SUB_HEADING_IV$/,/^$/ s/^LBL_B1.*/DERP/' \
    -e '/^DIVERSITY_REIGNS$/,/^$/ s/^LBL_B1.*/DERP/'
如果您激活扩展正则表达式(
-r
在GNU
sed
中,
-E
在BSD或Mac OS X
sed
),那么您可以使用(BSD表示法,但这里唯一的区别是
-E
-r
):

这假设在副标题行上没有注释。如果可以发表评论,您必须在识别起始行的正则表达式上更加努力:

sed -E '/^(SUB_HEADING_IV|DIVERSITY_REIGNS)( *!.*)?$/,/^$/ s/^LBL_B1.*/DERP/'
我不清楚是否可以用
*
来开始“尾部评论”;如果是,请更换
[!*]
一起使用

在找到后面的
sed -E '/^(SUB_HEADING_IV|DIVERSITY_REIGNS)$/,/^$/ s/^LBL_B1.*/DERP/'
sed -E '/^(SUB_HEADING_IV|DIVERSITY_REIGNS)( *!.*)?$/,/^$/ s/^LBL_B1.*/DERP/'
 sed -E '/^(SUB_HEADING_II|SUB_HEADING_IV)$/,/^(SUB_HEADING_I|SUB_HEADING_II|SUB_HEADING_III|SUB_HEADING_IV)$/ {
         s/^LBL_B1.*/DERP/; }'
SH=( "SUB_HEADING_I" "THE_AUTOMOBILE" "A_SUBMARINE" "SUB_HEADING_II"
     "TRANSVERSE_COGITATION" "DIAMETRICALLY_OPPOSED" "SUB_HEADING_III"
     "CODSWALLOP" "SUB_HEADING_IV"
   )
EH="$(IFS="|"; echo "/^(${SH[*]})\$/")"
sed -E '/^(SUB_HEADING_II|SUB_HEADING_IV)( *[!*].*)?$/,'"$EH"' s/^LBL_B1.*/DERP/'
SH=( "PLANES" "THE_TRAINS" "AN_AUTOMOBILE" "BUSES" "SUBMARINES" )
EH="$(IFS="|"; echo "/^(${SH[*]})([ !*].*)?$/")"
sed -E '/^BUSES([ !*].*)?$/,'"$EH"' s/^HUGE.*/DERP/' data

SH=( "PLANES" "THE_TRAINS" "AN_AUTOMOBILE" "BUSES" "SUBMARINES" )
EH="$(IFS="|"; echo "/^(${SH[*]})([ !*].*)?\$/")"
sed -E '/^SUBMARINES([ !*].*)?$/,'"$EH"' s/^HUGE.*/DERP/' data
$ bash -x script.sh
+ '[' -f /etc/bashrc ']'
+ . /etc/bashrc
++ '[' -z '' ']'
++ return
+ alias 'r=fc -e -'
+ SH=("PLANES" "THE_TRAINS" "AN_AUTOMOBILE" "BUSES" "SUBMARINES")
++ IFS='|'
++ echo '/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/'
+ EH='/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/'
+ sed -E '/^BUSES([ !*].*)?$/,/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/ s/^HUGE.*/DERP/' data
*
* Header comments
*

PLANES
!
! COMMENTS
!
BIG MEDIUM ##.### ##.###
BIG SMALL ##.### ##.###
...
SMALL SMALL ##.### ##.###
THE_TRAINS
!
! COMMENTS
!
MEDIUM MEDIUM SMALL ##.### ##.### ! COMMENT STUFF
MEDIUM SMALL SMALL ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG ##.### ##.###



AN_AUTOMOBILE 0.1 shift red
!
! COMMENTS
SMALL SMALL SMALL SMALL ##.### ##.### ##.###
SMALL MEDIUM SMALL SMALL ##.### ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG SMALL ##.### ##.### ##.###

BUSES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
LARGE ##.### ##.### ## !
SUBMARINES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
HUGE ##.### ##.### ## !
+ SH=("PLANES" "THE_TRAINS" "AN_AUTOMOBILE" "BUSES" "SUBMARINES")
++ IFS='|'
++ echo '/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/'
+ EH='/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/'
+ sed -E '/^SUBMARINES([ !*].*)?$/,/^(PLANES|THE_TRAINS|AN_AUTOMOBILE|BUSES|SUBMARINES)([ !*].*)?$/ s/^HUGE.*/DERP/' data
*
* Header comments
*

PLANES
!
! COMMENTS
!
BIG MEDIUM ##.### ##.###
BIG SMALL ##.### ##.###
...
SMALL SMALL ##.### ##.###
THE_TRAINS
!
! COMMENTS
!
MEDIUM MEDIUM SMALL ##.### ##.### ! COMMENT STUFF
MEDIUM SMALL SMALL ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG ##.### ##.###



AN_AUTOMOBILE 0.1 shift red
!
! COMMENTS
SMALL SMALL SMALL SMALL ##.### ##.### ##.###
SMALL MEDIUM SMALL SMALL ##.### ##.### ##.### ! COMMENT STUFF
...
BIG BIG BIG SMALL ##.### ##.### ##.###

BUSES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
LARGE ##.### ##.### ## !
SUBMARINES
SMALL ##.### ##.### ## !
MEDIUM ##.### ##.### ## !
...
DERP
$