使用awk或bash替换每个mth行的第n个字段

使用awk或bash替换每个mth行的第n个字段,bash,awk,Bash,Awk,对于包含以下类似项的文件: foo 1 6 0 fam 5 11 3 wam 7 23 8 woo 2 8 4 kaz 6 4 9 faz 5 8 8 如何使用bash或awk将每个mth行的第n个字段替换为相同的元素 例如,如果n=1,m=3,元素=wot,则输出为: foo 1 6 0 fam 5 11 3 wot 7 23 8 woo 2 8 4 kaz 6 4 9 wot 5 8 8 我知道您可以使用例如 awk

对于包含以下类似项的文件:

foo  1  6  0
fam  5  11  3
wam  7  23  8
woo  2  8  4
kaz  6  4  9
faz  5  8  8
如何使用bash或awk将每个mth行的第n个字段替换为相同的元素

例如,如果n=1,m=3,元素=
wot
,则输出为:

foo  1  6  0
fam  5  11  3
wot  7  23  8
woo  2  8  4
kaz  6  4  9
wot  5  8  8
我知道您可以使用例如

awk 'NR%7==0' file
到目前为止,我一直试图记住这一点,但没有用。。。我还需要保留文件的其余部分

我更喜欢使用bash或awk来回答问题,但sed解决方案也会有所帮助。这三方面我都是初学者。请解释你的解决方案

awk -v m=3 -v n=1 -v el='wot' 'NR % m == 0 { $n = el } 1' file
然而,请注意,字段间空白不能保证按原样保留,因为
awk
通过任何一次空白将一行拆分为字段;写入时,修改行的输出字段将用单个空格分隔。
但是,如果输入字段始终由2个空格分隔,则可以通过向
awk
调用添加
-F'-v OFS='
来有效地保留输入空白

  • -vm=3-vn=1-vel='wot'
    定义Awk变量
    m
    n
    el

  • NR%m==0
    是一种模式(条件),每第m行的计算结果为true

    • {$n=el}
      是用变量
      el
      替换输入行第n个字段的关联操作,导致使用默认为空格的输出字段分隔符
      OFS
      隐式重建行
  • 1
    是一种常用的Awk速记,用于打印(可能修改过的)手头的输入行


少运动多运动。虽然我可能倾向于使用
awk
解决方案,但在bash中,您也可以依靠带有子字符串替换的参数扩展来替换每个mth行的第n个字段。基本上,您可以读取每一行,保留空格,然后检查行数,例如,如果
c
是行计数器,
m
mth
行的变量,则可以使用:

    if (( $((c % m )) == 0))    ## test for mth line
如果该行是替换行,则可以在恢复默认分词后将每个单词读入数组,然后使用数组元素索引
n-1
提供替换(例如
${line/find/replace}
${line/“${array[$((n-1))]}/replace}

如果不是替换行,只需输出未更改的行即可。下面是一个类似的简短示例(您可以根据需要添加其他验证)

n=1
m=2
e=baz

$ bash replmn.sh dat/repl.txt 1 2 baz
foo  1  6  0
baz  5  11  3
wam  7  23  8
baz  2  8  4
kaz  6  4  9
baz  5  8  8
n=3
m=2
e=99

$ bash replmn.sh dat/repl.txt 3 2 99
foo  1  6  0
fam  5  99  3
wam  7  23  8
woo  2  99  4
kaz  6  4  9
faz  5  99  8
awk
解决方案较短(并避免了在
$line
中重复出现替换字符串的问题),但两者都需要类似的字段存在性验证等。。从两者中学习,如果你有任何问题,请告诉我

$ bash replmn.sh dat/repl.txt 1 2 baz
foo  1  6  0
baz  5  11  3
wam  7  23  8
baz  2  8  4
kaz  6  4  9
baz  5  8  8
$ bash replmn.sh dat/repl.txt 3 2 99
foo  1  6  0
fam  5  99  3
wam  7  23  8
woo  2  99  4
kaz  6  4  9
faz  5  99  8