使用 sed 进行模式替换

使用 sed 进行模式替换

谁能建议如何解决这个问题?假设我有一个文件,并且我想用一些动态值替换匹配行中第一次出现的模式。这里的模式是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 的事情:

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

shell 需要封闭''"$count"对来正确扩展变量以在 sed 命令内使用。

甚至更短(感谢 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

相关内容