如何使用awk填写以下字段的空格?

时间:2015-12-04 01:07:23

标签: awk

如果我有文件:

  1 0 1
1 1   0
0 0   1

我如何用以下栏目中的数字(如果有的话)填写空格,以便获得:

1 1 0 1
1 1 0 0
0 0 1 1

我试过了:

awk '{
         for (i=1;i<=NF;i+=2) {
             if ((($i)==" ") && ($(i+1)!=" ")) {
                 ($i)==($(i+1))
            }
                    print
        }
    }'

但我没有得到所需的输出。我想为每个其他列执行此操作,因此for循环中的+=2

或者,如果awk有办法忽略空格,我的问题可以解决吗?有办法吗?

谢谢。

6 个答案:

答案 0 :(得分:4)

使用FIELDWIDTHS的GNU awk:

$ cat tst.awk
BEGIN { FIELDWIDTHS="1 1 1 1 1 1 1"; OFS="" }
{
    for (i=(NF-2);i>0;i-=2) {
        $i = ($i==" " ? $(i+2) : $i)
    }
    print
}

$ awk -f tst.awk file
1 1 0 1
1 1 0 0
0 0 1 1

请注意,这会向后传播值,因此即使多个连续值丢失,也会填充它们。如果最后一个值丢失,您没有说要做什么,所以这假设不会发生或者您没事如果结果是空白的结果。

答案 1 :(得分:2)

替代sed

$ sed -r 's/  ([0-9])/\1 \1/'

答案 2 :(得分:1)

本着Unix的精神,这是<head> <title>story : cat</title> </head> <a class="results" href="www.hello.com" title="">title</a> import json fp =open('/path/tp/my/file') mystr = fp.read() fp.close() data = json.loads(mystr) 的易于理解的组合:

sed
  • awk为输入中缺少的字段填写sed 's/^ /@/; s/ / @/g' file | awk '{ for (i=1;i<=NF;i+=2) { if ($i=="@") $i = $(i+1) } print }'
    • sed 's/^ /@/; s/ / @/g'@替换空的第一个字段(感谢将正则表达式锚定到s/^ /@/行的开头)
    • @^替换任何其他空字段(由于使用s/ / @/g',可能多个)。
  • 由此产生的一致数量的字段允许安全使用@及其默认算法,即通过空白运行将输入拆分为字段。
  • 在问题中,然后检查每个其他字段(从第1个开始) - 对于g,在这种情况下 - 并且,如果匹配,则替换为相应的下一个字段的值。

答案 3 :(得分:1)

以下 sed 脚本处理具有多个数字/字符的数字和非数字数据。它通过使用 test 重复替换来处理多列空白的情况,直到替换不再成功:

sed ':a; s/  \([^ ]\+\)/\1 \1/g; ta'

使用 awk 一个类似的解决方案(可能效率较低,因为它与替换中不使用 g 标志后缀的情况相似)更加冗长 - 更不用说&#34;棘手&#34;为了正确:

awk '{ while(match($0, /  [^ ]+/)) { $0 = substr($0, 1, RSTART-1) substr($0, RSTART+2, RLENGTH-2) substr($0, RSTART+1, length($0)-RLENGTH+2) } print }'

两种实现都保留尾随空白并打印空白行。

答案 4 :(得分:0)

gawk的

awk -F '  ' 'NF>1&&$2~/^[0-9]|^ [0-9]/{a=+$2;if(length($1)<2){sub("$",a,$1)}else{sub("  "," "a)}}1' file
1 1 0 1
1 1 0 0
0 0 1 1

答案 5 :(得分:-1)

谢谢大家的好评!我还编写了一个更笨重的解决方案,但我必须在sed之前使用awk

我首先将FS更改为\t以获取:

    1   0   1
1   1       0
0   0       1

sed 's/ /x/g' file |

awk 'BEGIN {FS=OFS="\t"} {
        for (i=1;i<=NF;i+=2) {
            if ($i=="x") {
                $i=($(i+1))
        }
    }
}1'

这给出了:

1   1   0   1
1   1   0   0
0   0   1   1