从没有分隔符的文本文件中提取列

从没有分隔符的文本文件中提取列

我有一个很大的文本文件,它基本上是一个数据流,每一行几乎都压缩在一起。我被要求调查某些列中某些数据的失败。数据不以任何方式分隔。不过,我确实有一个“列”长度列表以及关于每个“列”中是否有相关数据的评论。

我会使用 Excel,但 Excel 按列分隔的限制为每行 1000 个字符,而每行远远超出此范围。其中许多字段都有 30 个空格的字符串作为填充符,并且至少有 15 个左右......我希望解析这些指定的“空”字段。

我需要的是一种可以输入文件的方法,并使用我可以提供的数组,该数组具有列长度,也许还有一个像“X”这样的标记来忽略我想要忽略的相应列,让它吐出一个新的带有分隔符的文件,然后我可以将其反馈到 Excel 中进行分析。

例如,如果我有一个包含一行的文件aaaaaabbbbbccccdddddeeeffffff,我将这个文件与一个数组一起输入,它会在该行中[6 5 4X 5 3X 6]吐出一个文件。aaaaaa^bbbbb^ddddd^ffffff

有没有办法可以用grep,awk或 来完成此操作sed

提前致谢。

答案1

短的cut命令方式:

样本input.txt内容:

aaaaaabbbbbccccdddddeeeffffff
wwwwwwddddd111133333xxxaaaaaa
ffffff00000sssszzzzz000rrrrrr

工作:

cut -c 1-6,7-11,16-20,24-29 --output-delimiter=^ input.txt
  • -c- 仅选择字符

  • 1-6,7-11,16-20,24-29- 字符位置连续范围,灵活可调

  • --output-delimiter=^- 输出字段分隔符,您可以将其调整为您想要的任何内容


输出:

aaaaaa^bbbbb^ddddd^ffffff
wwwwww^ddddd^33333^aaaaaa
ffffff^00000^zzzzz^rrrrrr

答案2

如果您有 GNU awk,您可以指定显式字段宽度,例如

$ printf 'aaaaaabbbbbccccdddddeeeffffff\n' | 
    gawk -v FIELDWIDTHS="6 5 4 5 3 6" -v OFS="^" '{print $1, $2, $4, $6}'
aaaaaa^bbbbb^ddddd^ffffff

从版本 4.2 开始,您可以使用语法跳过字符n:m,例如

printf 'aaaaaabbbbbccccdddddeeeffffff\n' |
   gawk -v FIELDWIDTHS="6 5 4:5 3:6" -v OFS="^" '{$1=$1} 1'
aaaaaa^bbbbb^ddddd^ffffff

(仅强制使用指定的字段宽度$1=$重新评估)。$0

参见示例GNU Awk 用户指南:4.6 读取固定宽度数据

答案3

如果没有看到您的确切输入和所需的输出,很难说,但是......

sed -e "$(
  printf '%d\n' 6 5 4 5 3 6 |
    awk '
      {
        f[NR] = f[NR-1] + $1
      }
      END {
        for (i=NR; i>0; i--) {
          printf "s/./&^/%d\n", f[i]
        }
      }
    '
)" infile.txt | cut -d^ -f1,2,4,6

未经测试。没有错误,我保证。 ;)


好的,我测试过。我错过了最后的大括号END。没有其他错误。在示例输入上完美运行。输出是:

aaaaaa^bbbbb^ddddd^ffffff

答案4

改进版本罗曼·佩雷克雷斯特的cut回答,带有列数组解析器,包括X后缀以显示要跳过多少列。

加载 array $n,并创建一个函数将数组解析为数字cut -c

n=(6 5 4X 5 3X 6)
col_array() { j=$(h=0; 
                  for f in $@; do 
                      g=${f/[Xx]};
                      i=$((h+1));
                      h=$((h+g));
                      [ $g = $f ] && echo -n $i-$h,
                  done;) ; 
              echo ${j%,}; }

文件输入.txt包含:

aaaaaabbbbbccccdddddeeeffffff
wwwwwwddddd111133333xxxaaaaaa
ffffff00000sssszzzzz000rrrrrr

col_array()与以下一起使用cut

cut -c $(col_array  ${n[@]}) --output-delimiter=^ input.txt

输出:

aaaaaa^bbbbb^ddddd^ffffff
wwwwww^ddddd^33333^aaaaaa
ffffff^00000^zzzzz^rrrrrr

并不严格需要数组,因为col_array()会解析它的参数:

cut -c $(col_array 3 5X 7) --output-delimiter=^ input.txt

输出:

aaa^bbbcccc
www^ddd1111
fff^000ssss

相关内容