1

我有一个数据集,我从 Google 电子表格中剪切并粘贴到我的文本编辑器(Sublime Text 2)中,并且该数据集与我的处理需求不太匹配。

在它来自电子表格的形式中,数据以一行字符串开始,每列一个字符串,然后是多行数据;在数据行中,每一列都有值1或为空白。我不知道数据来自电子表格时是否是制表符分隔的,但是在将其粘贴到文本文件中之后却不是。如果1一行中的最后一个不在最后一列中,则该行用空格填充,直到但不包括最后一列。

我尝试用 做一些事情awk,但我不知道如何解决空格既是分隔符又是列值的事实。接下来,我尝试了一些带有 的命令sed,包括用零替换重复的空格,并用管道连接到另一个sed替换10为 的命令1 0,但后来我有时会插入额外的零,我不知道在相应的行中发生了什么。

这是一些示例数据(真实文件中有 13 列)。我$在最后一个字符之后添加了字符,所以你可以看到这些行被填充了多远。

"1" "2" "3" "4"                           "1" "2" "3" "4"
  1 1 $                                   0 1 1 0
1     1 $                                 1 0 0 1
  1   $                                   0 1 0 0
1 1   1 $                                 1 1 0 1

我想得到类似 right 的东西(然后我不关心行结束的地方),所以我可以用awk.

顺便说一句,我已经看到了这个问题,它并没有解决我的问题,因为那里的解决方案基于文件是制表符分隔的事实,在“空”单元格中根本没有任何价值。重申一下,我的文件是用空格分隔的,空单元格中有空格。

4

3 回答 3

1

我的第一次尝试并不好。所以我的第二次 第三次第四次尝试根据修改后的输入自动确定列数:

awk 'NR==1{for(;N<NF;++N)sp=" 0"sp}NR>1{$0=" "$0;sub(" +$","");gsub("  "," 0");$0=substr($0sp,2,2*N-1)}1'<<EOT
"1" "2" "3" "4"
  1 1 
1     1 
  1   
1 1   1 
EOT

第一个空格是偶数,中间是奇数,所以我在开头添加了一个空格,以便在两种情况下使用相同的 gsub。目前尚不清楚存在多少尾随空格,因此脚本只是将它们切碎。它包含0字段次数的数量。Substr从 2 开始剪切添加的前导空格,并持续到(number of fields)*2-1字符以剪切尾随空格。

输出:

"1" "2" "3" "4"
0 1 1 0
1 0 0 1
0 1 0 0
1 1 0 1
于 2013-04-20T20:16:26.973 回答
0

试图解释为什么一个问题很难,这对你解决它的机会是有好处的。正因为想到这里的解释,我也想出了一个解决办法=)

该解决方案sed主要分为三个步骤:

  1. 用 0替换所有空的第一列:

    cat datafile.txt | sed 's/^ /0 /g'
    
  2. 用 0替换所有空的最后一列:

    cat datafile.txt | sed 's/^ /0 /g' | sed 's/  $/  0/g'
    

    在这里,我不得不对正则表达式中的空格数量进行一些试验,以将所有新零对齐。

  3. 用 0替换所有空的列:

    cat datafile.txt | sed 's/^ /0 /g' | sed 's/  $/  0/g' | sed 's/  / 0/g'
    

    在这里,我还尝试将 0 放在替换正则表达式中的第一个或最后一个以使其正确。

当然,完成此操作后,我通过> datafile-clean.txt在末尾标记 on 将输出重定向到文件。

可能有一种更优雅的方法可以做到这一点,所以如果你有一个,请发布它,即使我个人不再需要该解决方案。

更新:如评论中所示,此解决方案可以改进很多。我将把原始解决方案留在这里,因为我认为它的作用和顺序更清楚,但可能应该使用它。

首先,我们不需要那么多管道;相反,我们在-e上使用标志sed

sed -e 's/^  /0 /' -e 's/  $/ 0/' -e 's/  / 0/g' datafile.txt

鉴于具有列标题的第一行没有任何双空格,这可以按原样工作。如果是这样,则可以只使用tail -n +2 datafile上述sed命令读取文件并通过管道传输。

于 2013-04-20T17:41:26.540 回答
0
sed 's/ /0/g;s/10/1 /g;s/00/0 /g;s/$/0 /' datafile.txt | cut -c 1-7
于 2013-04-21T14:32:54.520 回答