【问题标题】:How to get first n characters of each line in unix data file如何获取unix数据文件中每行的前n个字符
【发布时间】:2013-01-22 15:50:35
【问题描述】:

我正在尝试从 unix 数据文件中获取前 22 个字符。这是我的数据如下所示。

前 12 个字符是第 1 列,接下来的 10 个字符是第 2 列。

000000000001199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-
000000000002199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-
000000000003199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-
000000000004199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-
000000000005199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-
000000000006199998000180000     DUMMY RAG #         MFR NOT ST            1999980    ZZ-            0        0              0ZZ-

【问题讨论】:

  • 您想要文件的前 22 个字符,还是每行的前 22 个字符?如果您想要每一行的数据,您应该修改问题。如所问,dd 是您要从文件中获取前 22 个字符的工具。
  • 我是通过寻找 OP 最初在标题中描述的内容而不是他真正想要做的事情来发现这一点的(在我编辑时,标题更好地反映了这一点,@WilliamPursell解释了两种意图的区别)。但是,如果有人在搜索 take the first n characters of a file 时遇到这个问题,here' 的答案,正如 William 所建议的那样使用 dd

标签: linux unix awk cut


【解决方案1】:

cut:

$ cut -c-22 file
0000000000011999980001
0000000000021999980001
0000000000031999980001
0000000000041999980001
0000000000051999980001
0000000000061999980001

如果我理解第二个要求,您希望将前 22 个字符分成长度为 10 和 12 的两列。sed 是最好的选择:

$ sed -r 's/(.{10})(.{12}).*/\1 \2/' file
0000000000 011999980001
0000000000 021999980001
0000000000 031999980001
0000000000 041999980001
0000000000 051999980001
0000000000 061999980001

【讨论】:

  • -r 有什么作用?我已经尝试过这个 sed 命令,但我收到一条错误消息,通知我 -r 是非法选项
  • @interstellar 与 GNU sed 它打开扩展正则表达式,BSD sed 的等效选项是 -E。
  • 根据性能,这似乎在读取第一个 n 字符之前读取了整个文件。有没有办法避免读取整个文件?
  • @JoshuaPinter 您可以使用head 仅读取前n 行,例如,限制为前20 行:head -n 20 file | cut -c-22
  • @ChrisSeymour 谢谢。我也试过了,但事实证明我们正在处理的文件是一行(!),但有数百万个字符。
【解决方案2】:

sudo_O 提供了不错的 cut 和 sed 解决方案,我只是添加了一个 awk 单行:

awk 'BEGIN{FIELDWIDTHS="22"} {print $1}' file

echo "000000000001199998000180000     DUMMY RAG"|awk 'BEGIN{FIELDWIDTHS="22"} {print $1}'
0000000000011999980001

使用空字符(这取决于您的要求,您想跳过空格或者您想在输出中包含并计算它们)

如果空格也应该计算并显示在输出中:(您不必更改上面的 cmd)

echo "0 0 0 0 00000001199998000180000"|awk 'BEGIN{FIELDWIDTHS="22"} {print $1}'                                                                         
0 0 0 0 00000001199998

如果您想跳过这些空格: (又快又脏)

echo "0 0 0 0 00000001199998000180000"|sed 's/ //g'|awk 'BEGIN{FIELDWIDTHS="22"} {print $1}'                                                            
0000000000011999980001

【讨论】:

    【解决方案3】:

    这实际上可以在 Bash 中完成,而无需使用任何外部程序(使用它的脚本必须以 #!/bin/bash 而不是 #!/bin/sh 开头,并且不会与 POSIX shell 兼容)使用表达式 ${VARIABLE:offset:length}(其中 :length 是可选):

    #!/bin/bash
    
    STR="123456789"
    
    echo ${STR:0:1}
    echo ${STR:0:5}
    echo ${STR:0:10}
    echo ${STR:5:10}
    echo ${STR:8:10}
    

    会有这样的输出:

    1
    12345
    123456789
    6789
    9
    

    请注意,起始偏移量从零开始,长度必须至少为一。您还可以使用括号中的负偏移量从字符串的右侧偏移:

    echo ${STR:(-5):4}
    
    5678
    

    要读取文件,重复获取每行的前 8 个字符,并将它们打印到终端,使用 while 循环,如下所示:

    while read LINE
        do echo "${STD:0:8}"
    done < "/path/to/the/text_file"
    

    这里有一个非常有用的资源,您需要了解 Bash 字符串操作:https://tldp.org/LDP/abs/html/string-manipulation.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-28
      • 2022-09-27
      • 2014-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多