我有一个字符串值存储在一个变量中:
PTYPE="Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home"
我想找到&用NOTHING之类的值替换Other。所有值都存储在变量中。
WhatToChange=Other
NewValue=NOTHING
echo $PTYPE|sed -e "s@${WhatToChange}@${NewValue}@g"
这取代了其他的所有出现,并获得了类似于的输出
NOTHING Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home
有什么办法可以让我只更改确切的一个吗?${WhatToChange}
的位置是可变的。
由于您有定义良好的字段,并且想要精确匹配,awk可能比sed更容易使用;至少,您不必为在sed
表达式中使用字符串而担心转义:
echo "Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home" |
awk -v old="Other" -v new="NOTHING"
'BEGIN {FS = OFS = "|"} {for(i=1;i<=NF;i++) if($i == old) $i = new} 1'
输出:
Other Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home
要匹配确切的字符|
或行首,请使用([|]|^)
。
要匹配确切的字符|
或行尾,请使用([|]|$)
。
要仅在适当的时候将|
放回原位,请将其存储在匹配组中,并使用1
或2
:引用这些组
PTYPE="Other Farm|Raised Ranch|Farm house|Other|A-Frame|Log Home"
WhatToChange=Other
NewValue=NOTHING
sed -re "s@(^|[|])${WhatToChange}($|[|])@1${NewValue}2@g" <<<"$PTYPE"
作为输出发射:
Other Farm|Raised Ranch|Farm house|NOTHING|A-Frame|Log Home
并且即使CCD_ 10在列表的开头或末尾匹配。
为了好玩,一些perl:
这类似于@Charles的sed解决方案:注意CCD_ 11;改变";值被视为文本。
echo "$PTYPE" | perl -spe '
s{ (?:^||)K Q$WhatToChangeE (?=||$) }{$NewValue}gx
' -- -WhatToChange=Other -NewValue=NOTHING
这就像@Fravadona的awk解决方案:
echo "$PTYPE" | perl -F'[|]' -sane '
print join "|", map {$_ eq $WhatToChange ? $NewValue : $_} @F
' -- -WhatToChange=Other -NewValue=NOTHING
怎么样
echo ${PTYPE//$WhatToChange/$NewValue}
更新:
我刚刚意识到,只有当WhatToChange
是两个分隔符(|
(之间的全部内容时,才应该进行替换。在这种情况下,我们也可以在bash中完成(不需要恢复到子进程(:
if [[ $PTYPE =~ (.*[|]|^)$WhatToChange([|].*|$) ]]
echo "${BASH_REMATCH[1]}${NewValue}${BASH_REMATCH[2]}"
fi
更新(基于Fravadona的评论(:
以这种方式使用,WhatToChange
被解释为正则表达式。如果您想捕捉字符串的变化,例如,这可能很有用
WhatToChange='[Oo]ther' # to catch Other and other
如果你总是想有一个文字匹配,你必须引用变量:[[ $PTYPE =~ (.*[|]|^)"$WhatToChange"([|].*|$) ]]
这可能对你有用(GNU sed&bash(:
<<<"$PTYPE" sed 'y/|/n/;s/^'"$WhatToChange"'$/'"$NewValue"'/mg;y/n/|/'
将$PTYPE
作为here字符串输入sed。
将|
分隔符转换为换行符。
将每个匹配行的$WhatToChange
替换为$NewValue
。
将换行转换回|
的。
注意:在替换命令中使用m
标志允许sed在多行模式下工作,这将在其自己的行中的分隔符之间显示每个值。
另一种选择:
sed -z 'y/|/x00/;s/^'"$WhatToChange"'$/'"$NewValue"'/mg;y/x00/|/;' file