仅当匹配项构成整个单词时,如何才能查找和替换?

仅当匹配项构成整个单词时,如何才能查找和替换?

我的脚本是:

n="y"
while [ "{n}" = "y" ]
if [ $n == "n" ];
then
  break;
fi
echo "n is $n"
do
        read -p "Enter the word to find = " word
        read -p "Enter word to replace = " replace
        echo "$word n $replace"
        #sed -i r.text.bak 's/$word/$replace/g' r.txt
        sed -i "s/$word/$replace/g" "test.txt"
echo "do you have further replacement? n or y"
read temp
n=$temp
done

我的问题是我也替换了部分匹配项。例如,对于这样的一行:

1.1.1.14 1.1.1.14567

我得到这个输出:

1.1.1.3  1.1.1.3567

但我期望:

1.1.1.3 1.1.1.14567

我该如何解决这个问题?

答案1

您需要以仅匹配整个单词的方式编写正则表达式。使用 GNU sed,您可以\b在单词边界使用 which 匹配:

sed -i "s/\b$word\b/$replace/g"

如果您知道那里总会有一个空格,您可以添加一个空格:

sed -i "s/ $word /$replace/g"

现在,您的脚本也存在一些问题。你的if ... break说法没有用,他们while已经在处理这个问题了。所有你需要的是:

#!/usr/bin/env bash
n="y"
while [ "$n" = "y" ]
do
    echo "n is $n"
    read -p "Enter the word to find = " word
    read -p "Enter word to replace = " replace
    echo "$word n $replace"
    sed -i "s/\b$word\b/$replace/g" test.txt
    echo "do you have further replacement? n or y"
    read temp
    n="$temp"
done

答案2

替换脚本中的以下行

sed -i "s/$word/$replace/g" "test.txt"

sed -i "s/$\bword\b/$replace/g" test.txt

请参考以下链接。 http://www.rexegg.com/regex-boundaries.html#wordboundary

答案3

在这里,我会使用perl.

WORD=$word REPLACE=$replace perl -pi -e '
  s/\b\Q$ENV{WORD}\E\b/$ENV{REPLACE}/g' file

sed(甚至 GNU sed)没有\Q\E您需要的等效项,以免$word被视为正则表达式。大多数sed实现不支持-i(或者它们以不同的语法支持)或\b.

\b匹配 a 之间的转换单词非词特点。

所以仍然会\b\Q1.1.2.3\E\b匹配1.1.2.3.4.非词

你还可以这样做:

WORD=$word REPLACE=$replace perl -pi -e '
  s/(?<!\S)\Q$ENV{WORD}\E(?!\S)/$ENV{REPLACE}/g' file

$word只要前面或后面没有非空格字符就匹配。 (使用(?<!)(?!)否定向后/向前运算符)。

请注意,perl默认情况下将使用 ASCII 字符。例如,一个单词字符只能是_a-zA-Z0-9\b\Q1.2.3\E\b将匹配1.2.3é\S匹配扩展 unicode 间距字符的各个字节)。对于非 ASCII 数据,您可能希望将该-CLSD选项添加到perl.

一些例子:

$ export WORD=1.1.1.3 REPLACE=REPLACE
$ printf '1.1.1.3-x 1.1.1.3\u2006 1.1.1.3.4 1.1.123 1.1.1.3\u20dd 1.1.1.3\ue9\n' > f
$ cat f
1.1.1.3-x 1.1.1.3  1.1.1.3.4 1.1.123 1.1.1.3⃝ 1.1.1.3é
$ perl -pe 's/\b\Q$ENV{WORD}\E\b/$ENV{REPLACE}/g' f
REPLACE-x REPLACE  REPLACE.4 1.1.123 REPLACE⃝ REPLACEé
$ perl -CLSD -pe 's/\b\Q$ENV{WORD}\E\b/$ENV{REPLACE}/g' f
REPLACE-x REPLACE  REPLACE.4 1.1.123 1.1.1.3⃝ 1.1.1.3é
$ perl -pe 's/(?<!\S)\Q$ENV{WORD}\E(?!\S)/$ENV{REPLACE}/g' f
1.1.1.3-x 1.1.1.3  1.1.1.3.4 1.1.123 1.1.1.3⃝ 1.1.1.3é
$ perl -CLSD -pe 's/(?<!\S)\Q$ENV{WORD}\E(?!\S)/$ENV{REPLACE}/g' f
1.1.1.3-x REPLACE  1.1.1.3.4 1.1.123 1.1.1.3⃝ 1.1.1.3é

$ sed "s/\b$WORD\b/$REPLACE/g" f
REPLACE-x REPLACE  REPLACE.4 REPLACE REPLACE⃝ 1.1.1.3é

答案4

sed -i "s/\s$word\s/$replace/g" "test.txt"

sed 还支持元字符\s

例子

var=world

echo "hello world"|sed -r "s/\s$var(\s|$)/.../g"

结果

hello...

请注意,有必要放置(\s|$)模式,因为一行可以以单词结尾,后跟行尾字符而不是空格

相关内容