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

如何用awk填充以下字段的空格?,awk,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)) }

如果我有文件:

  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
        }
    }'
awk'{
对于(i=1;igawk


awk-F''NF>1&&$2~/^[0-9]|^[0-9]/{a=+$2;if(长度($1)可选
sed

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

本着Unix的精神,这里是一个易于理解的
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'文件
awk'{

对于(i=1;i,带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

请注意,这会向后传播值,因此即使缺少多个连续值,这也会填充这些值。如果缺少最后一个值,您没有说明该怎么办,因此这假设不会发生,或者如果没有,您可以将结果设置为空。

以下sed脚本同时处理数字和非数字具有多个数字/字符的ic数据。它通过使用测试重复替换,直到替换不再成功,从而处理多列为空的情况:

sed ':a; s/  \([^ ]\+\)/\1 \1/g; ta'
使用awk时,类似的解决方案(可能效率较低,因为它与上面类似,在替代品中不使用g标志后缀)要复杂得多——更不用说“棘手的”问题了:

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 }'

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

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

sed 's/^ /@/; s/  / @/g' file | 
  awk '{
    for (i=1;i<=NF;i+=2) {
      if ($i=="@") $i = $(i+1)
    }
    print
  }'
我首先将
FS
更改为
\t
,以获得:

    1   0   1
1   1       0
0   0       1


您的尝试无效,因为awk使用空格来确定列。请在
for
循环上方添加
print NF
,以查看该操作。祝您好运。没有时间完成答案,但
gawk
可以执行固定宽度解析:尽管这可能是答案,但最好添加更多信息以帮助您完成此操作他不知道发生了什么。虽然不可读,但它确实能与
gawk
mawk
一起工作,但不能与BSD
awk
一起工作,其中
+$2
不会将空的
$2
值转换为
0
。这是一个聪明的
sed
唯一的选择。
sed/\([0-9]\)/\1\1/'
将使其符合POSIX。注意:如果输入行中有多个空字段,则需要使用
g
选项,但请注意,与OP尝试的
awk
解决方案不同,您无法将替换限制为奇数列索引(每隔一列).@ed——在命令行示例中,您是否会显式调用gawk而不是awk——因为FIELDWIDTHS(如上所述)是GNU扩展?(我会更改,但stackoverflow不允许更改一个字符。)很好。因为它可能不明显:每个
1
表示一个字段宽度,并且假定字段直接相邻(使用
FIELDWIDTHS
时没有字段分隔符的概念-忽略
FS
的值)。因此,值之间的空格也必须描述为字段,这解释了
FIELDWIDTHS
中需要7个条目(4个值+3个空格)@MichaelBack不,我会按原样称呼它。我们不希望人们将GNU sed作为gsed调用,或将GNU grep作为ggrep调用,等等。因此没有理由将GNU awk作为gawk调用。@ed——嗯……事实上,当我在工作中构建使用GNU扩展的awk脚本时,我总是专门调用gawk……如果我使用特定于mawk的命令行参数,情况也一样。相同对于sh vs bash,我尊重你的立场。如果你使用的扩展在mawk和gawk中都可用,但在其他Awk中不可用(例如,我相信mawk现在有gensub()),那会怎么样?我知道你的来历,但这似乎很有挑战性……如果你已经设法修改了你的输入以使用单个
\t
(选项卡)由于字段分隔符和空字段由一个空格表示,换句话说,如果您的输入现在看起来是这样的:
$。\t1\t0\t1\n1\t1\t。\t0\n0\t0\t.\t1'
在这里表示一个空格;与上面修改过的、基于选项卡的输入不匹配,但我假设这是您想要的),那么您根本不需要
sed
:只需将
if($i==“x”)
更改为
if($i==”)
,它应该可以工作。如果使用空格来表示空字段值和分隔符,则只需使用
sed
——如我的回答中所示。此外,通过更改输入数据的格式,您修改了问题的前提,并在这里有效地回答了不同的问题。因此,您的回答会分散您的注意力。事实上,我下次我会更留心我的第一个问题。谢谢。我认为你最初的问题很有趣(我投了赞成票),我认为你得到了很好的答案。然而,你在这里的回答让人分心,这就是为什么我投了反对票(我希望你删除它,这就是为什么我在投反对票之前等待的原因)。为了帮助未来的读者,我建议您接受最能回答您原始问题的答案。通常,我建议仅发布自己的答案,如果它确实是唯一回答问题的答案。
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