誰でもこの問題を解決する方法を提案できますか?ファイルがあり、一致する行に最初に表示されるパターンを動的値に置き換えたいとします。ここでのパターンはですas
。
ソースファイル:
a b c as aa as
as b d f aa sa
df as kf as df
ターゲットファイル:
a b c 1 aa as
2 b d f aa sa
df 3 kf as df
答え1
交換モードは毎回変わるので、これはおそらくもう少し奇妙なことです。
awk 'BEGIN { needle=1 } /as/ { $0=gensub( /as/, needle, 1, $0 ); needle=needle+1} { print } ' /path/to/input
上記は以下に適用されます。GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.0)
答え2
本当にsedを使用したい場合は、whileループ内で素敵に実行できます。
count=1;
while read line
do sed 's/as/'"$count"'/1' <<< "$line";
count=$((count+1));
done < source_file >> target_file
sed コマンド内で使用するために変数を適切に拡張するには、シェルに囲む''
ペアが必要です。"$count"
短いです(Kusalanandaに感謝します):
while read line
do sed 's/as/'"$(( ++count ))"'/1' <<< "$line";
done < source_file > target_file
パターンが見つかった場合にのみ増加させたい場合:
count=1;
while read line;
do sed '/as/! {q100}; s/as/'"$count"'/1' <<< "$line";
[[ "$?" -eq 0 ]] && (( ++count ));
done < source_file > target_file
答え3
そしてperl
$ perl -pe 'BEGIN{$n=1} s/as/$n++/e' file
a b c 1 aa as
2 b d f aa sa
df 3 kf as df
答え4
以下は、必要なタスクを実行する小さなPythonスクリプトです。
#!/usr/bin/env python
import sys
counter = 0
with open(sys.argv[1]) as fd:
for line in fd:
new_words = []
words = line.strip().split()
found = False
for word in words:
val = word
if word == 'as' and not found:
counter += 1
found = True
val = str(counter)
new_words.append(val)
print(" ".join(new_words))
そしてテストを実行するには:
$ ./substitute_dynamic_val.py input.txt
a b c 1 aa as
2 b d f aa sa
df 3 kf as df