web-dev-qa-db-ja.com

一致が単語全体を形成する場合にのみ、どのようにして検索および置換できますか?

私のスクリプトは:

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

どうすればこれを解決できますか?

5
dilshan

単語全体にのみ一致するように正規表現を記述する必要があります。 GNU sedを使用すると、\bこれは、単語の境界で一致します。

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
7
terdon

スクリプトの次の行を置き換えます

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

1
Amol

ここでは、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は、Wordnon-Wordの間の遷移に一致します。

したがって、\b\Q1.1.2.3\E\b非Wordであるため、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文字で動作します。たとえば、Word文字は_a-zA-Z0-9のみになります(\b\Q1.2.3\E\b1.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é
0