【问题标题】:Delimiter a row after a specified number of characters in the line of text with bash用bash在文本行中指定数量的字符后分隔一行
【发布时间】:2015-10-15 21:32:24
【问题描述】:

我有一个像这样的多行的 DataFile.txt

010255500060010123066000952367006U00000000001721SMITH JOHN
536818991298231894872315612145497F00000000001721STUART FEDERIC

一行中的每个字符代表一个数字(位置),需要根据每行中的字符位置添加分隔符(空格)。示例:

  • 案例 1:字符 #2
  • 案例 2:字符 #10
  • 案例 3:字符 #26
  • 案例 4:字符 #44
  • 案例 5:字符 #48

...等等

然后是这条规则和 NewFile.txt 的输出:

01 02555000 6001012306600095 2367006U0000000000 1721 SMITH JOHN
53 68189912 9823189487231561 2145497F0000000000 1721 STUART FEDERIC

【问题讨论】:

    标签: bash awk sed csv


    【解决方案1】:

    你可以使用gnu-awkFIELDWIDTHS

    awk 'BEGIN{FIELDWIDTHS = "2 8 16 18 4 100"; OFS=" "}
         {$1=$1; print}' DataFile.txt
    

    你明白了,

    01 02555000 6001012306600095 2367006U0000000000 1721 史密斯约翰 53 68189912 9823189487231561 2145497F0000000000 1721 斯图尔特·费德里克

    【讨论】:

    • 可以打高尔夫球到gawk -v FIELDWIDTHS="2 8 16 18 4 99" '{$1=$1}1'
    • 谢谢! @glennjackman 是另一种方式,它们都是在文件中进行更改的非常有用的方式。
    【解决方案2】:

    我会说:

    sed -E 's/(.{2})(.{8})(.{16})(.{18})(.{4})/\1 \2 \3 \4 \5 /' filename
    

    对于非常古老的 GNU sed,您可能必须使用 -r 而不是 -E(这是用于扩展的正则表达式语法。没有它,您将需要大量不完全有助于可读性的反斜杠)。

    这只是简单地捕获一组字母——.{n} 匹配 n 个任意字母——并用添加的空格重新组合它们。

    附录:

    如果使用的数字与问题中的相同很重要,请考虑 Perl:

    perl -pe 'for $i (48, 44, 26, 10, 2) { substr($_, $i, 0) = " "; }' filename
    

    ...因为替换零长度子字符串与插入相同。数字必须递减才能起作用,以免已经插入的空格弄乱了计数。

    请注意,这可能会提供比 sed 方法更差的性能(因为必须计算更多的中间字符串),这可能是也可能不是问题,具体取决于文件大小。但是,如果不考虑性能并且您更喜欢使用绝对位置而不是字段宽度,则此方法可行。

    【讨论】:

    • 感谢您的帮助,但我更喜欢 awk 方式
    猜你喜欢
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多