web-dev-qa-db-ja.com

文字列パターンをsedを使用したシーケンスに置き換えます

テキストファイル内の文字列を、できればsedを使用して1 2 3 4 5 67などの一連の数字に置き換えたい。

これが私が(検索文字列なしで)試したもので、うまくいくようです:

for i in {1..5};do echo $(seq 1 $i); done

出力:

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

しかし、私がこれを試すと:

for i in {1..5};do sed -i "s/abc/$(seq 1 $i)/g" test; done

次のエラーが発生します。

sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command
sed: -e expression #1, char 8: unterminated `s' command

置換文字列も角かっこで囲んでみましたが、うまくいかないようです。

最初のループ

for i in {1..5}

いくつかのパラメータを置き換えたいファイル名のグロブに置き換えられます。

1
smog

TL; DR:

これを回避する方法はいくつかありますが、サンプルケースで最もクリーンな方法は次のとおりです。

_for i in {1..5};do sed -i "s/abc/$(seq -s ' ' 1 $i)/g" test; done
_

つまり、seqに、各数値を区切るために1つのスペースを使用するように要求します。

説明:

これらのエラーが発生した理由は、次の出力が原因です。

_seq 1 5
_

ではありません:

_1 2 3 4 5
_

むしろ:

_1
2
3
4
5
_

また、$(seq 1 $i)コマンド置換 を二重引用符で囲んだため、通常の 単語分割 は実行されず、すべての改行(最後を除く)が実行されます。 seqユーティリティによる出力はそのままです。

したがって、実際のsedコマンドは次のようになります。

_sed -i "s/abc/1
2
3
4
5
/g" test
_

sedに関する限り、_s/abc/1_コマンドを指定したため、つまり、必要な最後の_/_がないため、これは受け入れられません。

echo $(seq 1 5)は二重引用符で囲まれていないため、$(seq 1 5)は_1 2 3 4 5_を出力します。したがって、単語分割はシェルのデフォルトの動作に従って行われます。

実際、次のようにサンプルケースを修正する場合があります。

_for i in {1..5};do sed -i "s/abc/$(echo $(seq 1 $i))/g" test; done
_

つまり、コマンド置換(元の_seq 1 $i_)inside別のコマンド置換(echo 1)を実行します。

$(echo ...)コマンド置換はnotではないサブシェルで実行されるため、これは二重引用符内でも機能します。 )「I-am-inside-a-double-quote」状態であるため、seqからの出力に対するワード分割はそこで実行されます

0
LL3

出力を一時ファイルにパイプしてから、一時ファイルを元のファイルの上に移動できます。また、mayは、一度に1行で操作することを意味します。その場合、gを削除する必要があります。

for i in {1..5}; do
    sed -e "s/abc/$(seq 1 $i)/" test > test.tmp
    mv test.tmp test
done
0
uanirudhx