我的文件中有几行,如下所示
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('SUN') NAME('CAT') TRASMIT('TRUCK') REPLACE
括号内的文本对于每一行都会改变。我正在尝试在MANAGER(在本例中为SUN)之后的括号内提取文本,将其存储为变量,然后用planet.SUN.star替换。
我尝试使用awk字段分隔符来提取括号之间的文本,并使用字段分隔符作为括号,但是我的结果不一致。有时,匹配字词MANAGER之后的括号内没有文字。
期望输出如下所示
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.SUN.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
答案 0 :(得分:1)
如果您选择Task
,请尝试:
Perl
输出:
word="MANAGER"
replacement="PLANET.SUN.STAR"
perl -pe "s/(?<=${word}\(')(.+?)(?='\))/${replacement}/" <<< "DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('SUN') NAME('CAT') TRASMIT('TRUCK') REPLACE"
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.SUN.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
是一个与(?<=${word}\(')
匹配的后置断言。MANAGER('
是匹配(?='\))/
的先行断言。')
是要替换的模式。我认为您不必仅为替换目的而分配(.+?)
变量,但是如果需要,修改代码很容易。
编辑
以下是根据OP的要求而更新的版本。
SUN
输入文字:
perl -pe "s/(?<=MANAGER\(')(.+?)(?='\))/PLANET.\$1.STAR/" text
输出:
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('SUN') NAME('CAT') TRASMIT('TRUCK') REPLACE
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('MOON') NAME('CAT') TRASMIT('TRUCK') REPLACE
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('JUPITER') NAME('CAT') TRASMIT('TRUCK') REPLACE
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.SUN.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.MOON.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.JUPITER.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
部分,并将字符串分成三部分:MANAGER('blah')
,MANAGER('
和blah
。')
与第一个匹配。正则表达式(?<=MANAGER\(')
称为断言为零宽度的正向后断言。它用作 anchor ,并且匹配的字符串不包含在捕获组中。该性质对于重新使用原始子字符串(第一部分)而不影响效果很有用。(?<=pattern)
与第3个匹配。正则表达式(?='\))
是一个零宽度正向超前断言,与第一个正则表达式类似。(?=pattern)
与被第一个正则表达式和第三个正则表达式包围的子字符串匹配。量词(.+?)
之后的?
导致最短匹配,否则正则表达式将尝试在单词边界上尽可能长地匹配。+
,并在单词之后添加PLANET.
。 .STAR
可以引用捕获的单词,然后替换部分看起来像$1
。因为脚本在双引号内,所以必须使用反斜杠。以下是一个PLANET.\$1.STAR
版本,它会产生相同的结果:
AWK
希望这符合要求。
答案 1 :(得分:0)
awk解决方案:
echo "DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('SUN') NAME('CAT') TRASMIT('TRUCK') REPLACE" \
| awk '{
# Look for the field starting with MANAGER(
for ( I=1 ; I <= NF ; I++ ) {
if ( $I ~ /^MANAGER[(]/ ){
MANAGER = $I
break
}
}
# Remove everything except our value
sub( /^MANAGER[(]\x27/, "", MANAGER )
sub( /\x27[)]$/, "", MANAGER )
# Rebuild the line with the new value
$I = "MANAGER(\x27PLANET." MANAGER ".STAR\x27)"
print
}'
答案 2 :(得分:0)
这与sed
并用标准替代形式sed "s/find/replace/"
使用捕获组和后向引用相当简单,其中{ {1}}包含捕获组find
,"MANAGER('\(.[^']*\)':
使用后向引用 replace
插入捕获的内容,例如
\1
通过您的示例,您将获得:
sed "s/MANAGER('\(.[^']*\)')/MANAGER('PLANET.\1.STAR')/"
要在变量中捕获$ echo "DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('SUN') NAME('CAT') TRASMIT('TRUCK') REPLACE" | \
sed "s/MANAGER('\(.[^']*\)')/MANAGER('PLANET.\1.STAR')/"
DEF QR('xxx.yyy.sss') USE(YES) DESC('Something') MANAGER('PLANET.SUN.STAR') NAME('CAT') TRASMIT('TRUCK') REPLACE
,您可以将命令替换与"SUN"
和类似的正则表达式一起使用,后跟参数扩展修剪外部单引号,例如
grep -o
输出结果:
var=$(echo "your_string" | grep -o "MANAGER('.[^']*')")
var="${var#*\'}"
var="${var%\'*}"
echo "var: $var"