如何在linux中将每行加倍并以不同的方式更改每行中的数字?

如何在linux中将每行加倍并以不同的方式更改每行中的数字?

输入文件如下所示:

1 0 0 000 3444
2 3 3 456 6875
3 0 0 023 3300
4 2 2 211 1000

第一:我想要每行都有 2 个副本:

1 0 0 000 3444
1 0 0 000 3444
2 3 3 456 6875
2 3 3 456 6875
3 0 0 023 3300
3 0 0 023 3300
4 2 2 211 1000
4 2 2 211 1000

第二:在每行的第一个副本中,3 应替换为 2,4 应替换为 1,在每行的第二个副本中,3 应替换为 1,4 应替换为 2(第一列是行名称)并且行号不应更改)。所以,最终输出变成:

1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000

有什么建议吗?我尝试了这个,但它不起作用:

awk '
      { tmp = $2; gsub("3", "2", $2); gsub("4", "1", $2); print}
      { $2 = tmp; gsub("3", "1", $2); gsub("4", "2", $2); print}
    ' < input > output

答案1

如何将每行加倍:看这里...
对于您的第二个请求,只需将第一个字段和整行保存到变量中,然后进行第一次更改,将第一个字段设置为初始值并打印,然后恢复行内容,进行第二次更改,设置第一个字段再次返回初始值并打印:

awk '{t=$1;l=$0;gsub(/3/, "2");gsub(/4/, "1");$1=t;print}
{$0=l;gsub(/3/, "1");gsub(/4/, "2");$1=t;print}' infile

答案2

Perl 似乎非常适合这种事情,因为它有一个内置的tr

$ perl -alne '
    @tmp=@F; 
    tr/34/21/ for @tmp[1..4]; print join " ", @tmp; 
    tr/34/12/ for @F[1..4]; print join " ", @F
  ' file
1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000

答案3

不太优雅,但使用 GNU 是可能的sed

h              # save in hold
s_^[0-9]\{1,\} __ # remove first column
s_3_A_g        # change 3 and 4 to A and B
s_4_B_g
x              # swap with hold
s_ .*$__       # remove everything but first column
G              # append from hold
s_\n_ _        # join lines (with space)
h              # save in hold space again
s_A_2_g        # first output -> 2, 1
s_B_1_g
p              # print first line
g              # restore from hold 
s_A_1_g        # second output -> 1, 2
s_B_2_g
# end of script, second line printed automatically

这将保存第一列(这样它就不会被更改),并构建该行的一个版本,其中所有剩余的 3 和 4 分别更改为 As 和 B。然后该行用于两个输出,首先使用21,然后反过来。

sed -f script.sed input > output

这假设您的输入仅包含数字和空格,即。A并且B还没有出现在那里。

相关内容