sed は while ループの変数を置き換えません。

sed は while ループの変数を置き換えません。

sedで変数の行番号を使用しようとすると単独で動作しますが、whileループを使用して同じことを行うと機能しません。

例えば。

cat file
den 
run
ten
run
fan

linenumber=2
replacetext=34
sed -i ""$linenumber"s/run/run\n"$replacetext"/" file

Output:
cat file
den
run
34
ten
run
fan

上記の操作では、変数拡張後にsedコマンドが生成されます。

しかし、whileループで同じ方法を使用すると、純粋なsedソリューションを使用してすべてのインスタンスをインクリメントする行番号に置き換えたいので、最初のインスタンスでのみ機能し、すべてのインスタンスでは機能しません。 awkまたはPerlソリューションは必要ありません。

例えば。

replacetext=1
while read in; do replacetext=$((replacetext++)) && sed ""$in"s/run/run\n"$replacetext"/" file; done <<< "$(cat file | grep 'run' -n | cut -f1 -d ':')"

期待される出力:一致するテキストはそれ自体で変わり、その後に改行文字と増分数字が続きます。

den 
run
2
ten
run
3
fan

得られた出力:

den
run
2
ten
run
fan

sedベースのソリューションのみが必要です。 whileループでどのような奇妙な動作が起こっているのか疑問に思います。動作しません。ループ変数に行番号の値が割り当てられているため、その行番号はsed内のその行のMacthedテキストを置き換えるために使用され、その後に改行文字と増分数字が続きます。

Sedは同じ変数行番号を指定すると機能するように見えますが、whileループでは機能しません。

ベストアンサー1

<<< 次の内容が正しい行番号のリストを取得するため、失敗します。元のファイルに

その後、ファイルを複数回編集し、追加行の挿入

したがって、最初のものを除くすべてのsedは次のように渡されます。無効な行番号s/// コマンドの場合。

1つの回避策は、行番号のリストを逆に置き換えることです。これにより、編集内容が前の番号に影響を与えません。

これはパイプ内のsedソリューションですが、少し奇妙です。

最初のsedは=演算子を使用して、パターンが見つかった行番号を取得します。 nl は各行の前にシリアル番号を追加します。 3 10

2番目のsedはsed式を出力します。これは各行を希望のsed編集に変換します(例:)10 s/$/\n3/

3 番目の sed は、stdin でこれらの編集内容を収集して適用し、ファイルをその場で編集します。この場合、それ自体が編集されます。

スクリプト自体は次のとおりです。

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'

sed -n -e "/${Pattern}/=" badSed |
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
    sed -i -f - badSed
 

これが彼自身にすることです:

#! /bin/bash

Pattern="[Ss]ed"

RegEx='[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*'
DoSed='\2 s/\$/\\n\1/'
1

sed -n -e "/${Pattern}/=" badSed |
2
    nl -ba |
    sed -e "s:${RegEx}:${DoSed}:" |
3
    sed -i -f - badSed
4

おすすめ記事