awk 范围模式中的反向引用
Backreferences in awk range pattern
我有一个脚本,其中包含有用的提示,可以让我提醒自己经常忘记的各种事情。目前看起来像这样(但有更多有用的提示):
#!/bin/bash
awk 'BEGIN{IGNORECASE = 1}/^.*''.*:$/,/^$/' <<'_EOF'
tip_header:
tip1:
actual tip
<-- white space to here
tip2:
another tip
<-- white space to here
something:
else with \weird $characters^~
another_header:
tip1:
tip1 for another_header
_EOF
然后我调用 tips tip_header
打印出 tip_header:
和 another_header:
之前的空行之间的所有内容(tip2:
之前的行有空格,所以不为空)或 tips tip1
从每个 tip1:
行打印到下一个空行。
我想更改 awk 表达式,使 endpat
匹配第一个空行,缩进与 begpat
中的相同,这样调用 tips tip1
就不会t 也打印出 tip2
。
类似于:
awk 'BEGIN{IGNORECASE = 1}/^([[:blank:]]*).*''.*:$/,/^$/' <<'_EOF'
但这不起作用(我不确定 how/if 是否可以在 awk 或其变体中使用反向引用)。我不反对用其他可以进行多行模式匹配的东西来替换 awk。
编辑:
运行 tips tip1
的当前输出是
brett@brett:~/tmp$ ./tips tip1
tip1:
actual tip
tip2:
another tip
something:
else with \weird $characters^~
tip1:
tip1 for another_header
期望的输出是
brett@brett:~/tmp$ ./tips tip1
tip1:
actual tip
tip1:
tip1 for another_header
同时保持
brett@brett:~/tmp$ ./tips tip_header
tip_header:
tip1:
actual tip
tip2:
another tip
something:
else with \weird $characters^~
首先,我要坚持@tripleee 是正确的,你应该使用适当的工具来解析 yaml 文件。
如果你真的想使用 awk,我会做一些像这样丑陋的事情(我试图做一个适用于任何 awk 版本的代码):
#!/bin/bash
awk -v search="" -F '' '
BEGIN{IGNORECASE = 1}
(!pos_char)&&([=10=] ~ (search ".*:")){
pos_char=1;
while($pos_char==" "){
pos_char+=1
}
print; next
}
prev_line == "" && NF && pos_char{
if(NF<pos_char){
pos_char = 0; next
}
for(i=1; i<=pos_char; i++){
if($i != " "){
pos_char = 0; next
}
}
}
pos_char{prev_line=[=10=];print}
' << '_EOF'
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
another_header:
tip1:
tip1 for another_header
_EOF
仅当您使用空格缩进时才有效。
至少你可以用这个方法去除空行上难看的空白字符。
输出:
$ ./tips tip
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
tip1:
tip1 for another_header
$ ./tips tip_header
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
$ ./tips tip1
tip1:
actual tip
tip1:
tip1 for another_header
$ ./tips tip2
tip2:
another tip
with carriage return
我有一个脚本,其中包含有用的提示,可以让我提醒自己经常忘记的各种事情。目前看起来像这样(但有更多有用的提示):
#!/bin/bash
awk 'BEGIN{IGNORECASE = 1}/^.*''.*:$/,/^$/' <<'_EOF'
tip_header:
tip1:
actual tip
<-- white space to here
tip2:
another tip
<-- white space to here
something:
else with \weird $characters^~
another_header:
tip1:
tip1 for another_header
_EOF
然后我调用 tips tip_header
打印出 tip_header:
和 another_header:
之前的空行之间的所有内容(tip2:
之前的行有空格,所以不为空)或 tips tip1
从每个 tip1:
行打印到下一个空行。
我想更改 awk 表达式,使 endpat
匹配第一个空行,缩进与 begpat
中的相同,这样调用 tips tip1
就不会t 也打印出 tip2
。
类似于:
awk 'BEGIN{IGNORECASE = 1}/^([[:blank:]]*).*''.*:$/,/^$/' <<'_EOF'
但这不起作用(我不确定 how/if 是否可以在 awk 或其变体中使用反向引用)。我不反对用其他可以进行多行模式匹配的东西来替换 awk。
编辑:
运行 tips tip1
的当前输出是
brett@brett:~/tmp$ ./tips tip1
tip1:
actual tip
tip2:
another tip
something:
else with \weird $characters^~
tip1:
tip1 for another_header
期望的输出是
brett@brett:~/tmp$ ./tips tip1
tip1:
actual tip
tip1:
tip1 for another_header
同时保持
brett@brett:~/tmp$ ./tips tip_header
tip_header:
tip1:
actual tip
tip2:
another tip
something:
else with \weird $characters^~
首先,我要坚持@tripleee 是正确的,你应该使用适当的工具来解析 yaml 文件。
如果你真的想使用 awk,我会做一些像这样丑陋的事情(我试图做一个适用于任何 awk 版本的代码):
#!/bin/bash
awk -v search="" -F '' '
BEGIN{IGNORECASE = 1}
(!pos_char)&&([=10=] ~ (search ".*:")){
pos_char=1;
while($pos_char==" "){
pos_char+=1
}
print; next
}
prev_line == "" && NF && pos_char{
if(NF<pos_char){
pos_char = 0; next
}
for(i=1; i<=pos_char; i++){
if($i != " "){
pos_char = 0; next
}
}
}
pos_char{prev_line=[=10=];print}
' << '_EOF'
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
another_header:
tip1:
tip1 for another_header
_EOF
仅当您使用空格缩进时才有效。 至少你可以用这个方法去除空行上难看的空白字符。
输出:
$ ./tips tip
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
tip1:
tip1 for another_header
$ ./tips tip_header
tip_header:
tip1:
actual tip
tip2:
another tip
with carriage return
something:
else with \weird $characters^~
$ ./tips tip1
tip1:
actual tip
tip1:
tip1 for another_header
$ ./tips tip2
tip2:
another tip
with carriage return