查找和替换字符串值中分隔符之间的完全匹配项



我有一个字符串值存储在一个变量中:

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

要匹配确切的字符|或行首,请使用([|]|^)

要匹配确切的字符|或行尾,请使用([|]|$)

要仅在适当的时候将|放回原位,请将其存储在匹配组中,并使用12:引用这些组

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

最新更新