我整天都在苦苦挣扎。试图在一行中只包含大括号内的变量。
线条看起来像这样:
blah blah [ae b c] blah [zv y] blah
我需要这样做:
blah blah [$ae $b $c] blah [$zv $y] blah
必须有一个简单的方法来做到这一点。但是,每当我尝试
$ echo "blah blah [ae b c] blah [zv y] blah" | sed 's/\[\(\b.*\b\)\]/$\1/g'
我得到了贪婪的匹配,只有一个变量:
blah blah $ae b c] blah [zv y blah
还有更好的东西吗? 谢谢,
答案 0 :(得分:2)
$ echo "blah blah [ae b c] blah [zv y] blah" | sed -r ':b; s/([[][^]$]* )([[:alnum:]]+)/\1$\2/g; t b; s/[[]([[:alnum:]])/[$\1/g'
blah blah [$ae $b $c] blah [$zv $y] blah
-r
这会打开扩展的正则表达式。
:b
这会创建一个标签b
。
s/([[][^]$]* )([[:alnum:]]+)/\1$\2/g
这会查找[
,后跟除]
或$
之外的任何内容,后跟空格,后跟任何字母数字字符。它将$
放在字母数字字符前面。
请注意,使[[]
与[
匹配的awk约定与[^]$]
匹配除]
和$
之外的任何内容。这比尝试使用反斜杠转义这些字符更容易。
t b
如果上面的命令导致替换,则将其分支回标签b
,以便再次尝试替换。
s/[[]([[:alnum:]])/[$\1/g
最后一步是查找[
后跟字母数字字符,并在它们之间放置$
。
因为使用了[[:alnum:]]
,所以此代码是unicode-safe。
在BSD sed(OSX)上限制了使用分号组合语句的能力。试试这个:
sed -E -e ':b' -e 's/([[][^]$]* )([[:alnum:]]+)/\1$\2/g' -e 't b' -e 's/[[]([[:alnum:]])/[$\1/g'
答案 1 :(得分:0)
要禁用它是贪婪的,而不是匹配任何字符,请匹配除右括号之外的任何字符:
sed 's/\[\(\b[^]]*\b\)\]/$\1/g'
使用sed无法完成您要执行的任务,因为无法使用常规语法描述上下文相关匹配。
答案 2 :(得分:0)
使用sed很难解决它。作为替代方案,您可以在Text::Balanced
模块的帮助下使用perl,它可以在平衡分隔符(如方括号)之间提取文本。每次调用都返回一个数组,其中包含分隔符之间的内容,它们之前的文本和它们之后的文本,因此您可以将$
符号的正则表达式应用于字符串的有意义部分。
perl -MText::Balanced=extract_bracketed -lne '
BEGIN { $result = q||; }
do {
@result = extract_bracketed($_, q{[]}, q{[^[]*});
if (! defined $result[0]) {
$result .= $result[1];
last;
}
$result[0] =~ s/(\[|\s+)/$1\$/g;
$result .= $result[2] . $result[0];
$_ = $result[1];
} while (1);
END { printf qq|%s\n|, $result; }
' infile
它产生:
blah blah [$ae $b $c] blah [$zv $y] blah
答案 3 :(得分:0)
sed 's/\[\([^]]*\)\]/[ \1]/g
:loop
s/\(\(\[[^]$]*\)\([[:blank:]]\)\)\([^][:blank:]$][^]]*\]\)/\1\$\4/g
t loop
s/\[ \([^]]*\)\]/[\1]/g' YourFile
[a b[c] d ]
$
,但没有一个(不是以$
开头)。对每个支架组执行此操作,但仅为每个组添加1个答案 4 :(得分:0)
这可能适合你(GNU sed):
sed -r 'h;s/\</$/g;T;G;s/^/\n/;:a;s/\n[^[]*(\[[^]]*\])(.*\n)([^[]*)[^]]*\]/\3\1\n\2/;ta;s/\n(.*)\n(.*)/\2/' file
制作当前行的副本。在所有词头界限的前面插入$
。如果没有替代品,则打印当前行并打包。否则,附加未掺杂行的副本,并在掺假当前行的开头插入换行符。使用替换和模式匹配使用换行符替换[...]
与原始匹配部分之间的行部分,以便将匹配向前移动到该行。完成所有匹配后,替换原始行的末尾并删除换行符。