【问题标题】:Insert a string at a specific position (fixed length file)在特定位置插入字符串(定长文件)
【发布时间】:2020-01-20 14:30:57
【问题描述】:

我试图在固定长度文件的每一行的 80 位置插入一个字符串“abcd”。

输入文件

1212121212121212121213231232345    00000003088 234235235321      MISS WAN
1212121212121212121213231232345    00000003088 324556346366      MISS NISCH
1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL
1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK

每条记录的长度分别是

awk '{print length}' temp.txt
74
76
77
79

我无法在 80 处插入数据,我已尝试以下命令

sed "s/.\{80\}/&abcd/" test.txt
awk -vFS="" -vOFS="" '{$80=$80"abcd"}1' test.txt

我想我应该先增加记录的长度,然后我才能使用上面的命令..
插入空格

sed -e "s/.\{75\}/&              /g" test.txt
sed 's/$/        /" test.txt

循环内

while read line
do
printf "$line        " >>temp.txt
done <test.txt

大多数情况下,上面的空格会被下一行修改并丢失一些内容,如下所示..

4044046160710301740053062257440    00000003088 850052246976      MISS WAN
    046160710301740053062257440    00000003088 850052246976      MISS NISCH
    046160710301740053062257440    00000003088 850052246976      MISS RACHEL
2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK

预期答案:

4044046160710301740053062257440    00000003088 850052246976      MISS WAN       abcd
4044046160710301740053062257440    00000003088 850052246976      MISS NISCH     abcd
4044046160710301740053062257440    00000003088 850052246976      MISS RACHEL    abcd
2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK  abcd

任何关于正确答案的指南都将不胜感激。

【问题讨论】:

  • 很好奇...您是否需要担心长度 >= 80 个字符的行,如果是,您如何处理当前位于 80+ 位置的字符?
  • 嗨@mar​​kp,现在位置 80 没有字符..

标签: bash unix awk sed ksh


【解决方案1】:

更简单的awk

$ awk '{printf "%-80s%s\n",$0,"abcd"}' file

1212121212121212121213231232345    00000003088 234235235321      MISS WAN       abcd
1212121212121212121213231232345    00000003088 324556346366      MISS NISCH     abcd
1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL    abcd
1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK  abcd

【讨论】:

    【解决方案2】:

    根据 OP 的要求,按长度 80 添加空格的解决方案: 如果您的 Input_files 中有控制 M 个字符并且您想删除它们,请使用:

    tr -d '\r' < Input_file > temp_file && mv temp_file Input_file
    

    然后运行以下代码:

    awk -v var="80" '{printf("%s%"var-length($0)+1"s%s\n",$0,OFS,"abcd")}' Input_file
    


    第二个解决方案(更通用的一个):您能否尝试以下,此解决方案将在整个 Input_file 中查找行的最大长度,并根据添加空格它和新输入的最后一个字段将与所有其他行对齐。

    awk '
    FNR==NR{
      len=length($0)>len?length($0):len
      next
    }
    {
      printf("%s%"len-length($0)+1"s%s\n",$0,OFS,"abcd")
    }
    '  Input_file  Input_file
    

    【讨论】:

      【解决方案3】:

      您可以使用gnu awk 命令:

      awk -v RS='\r?\n' -v p='80' -v s='abcd' '{
          pad=""; for (i=length(); i<=p; i++) pad=pad " "; print $0 pad s}' file
      

      1212121212121212121213231232345    00000003088 234235235321      MISS WAN        abcd
      1212121212121212121213231232345    00000003088 324556346366      MISS NISCH      abcd
      1212121212121212121213231232345    00000003088 547478657588      MISS RACHEL     abcd
      1212121212121212121213231232345    00000009781 313156475788      MR & MRS ROCK   abcd
      

      注意使用-v RS='\r?\n',它将记录分隔符设置为可选\r,后跟\n。这是为了解决输入文件有 DOS 换行符时的情况。

      For 循环从每行的长度开始到所需的位置(从变量p 中的命令行传递)并在pad 变量中附加一个空格。最后,我们打印每一行,然后是填充空间和新字符串。

      【讨论】:

      • 没有找到正确的...` awk -v p='80' -v s='abcd' '{ > pad=""; for (i=length(); i
      • 这是上述代码的工作演示:ideone.com/zO35sN 确保您的输入文件没有 DOS 行结尾。如果是,则先使用dos2unix 转换为 Unix 文件。
      • 谢谢伙计。 awk -v RS='\r?\n' -v p='80' -v s='abcd' '{pad=""; for (i=length(); i起到了神奇的作用。
      • 很高兴知道它有效,因为我怀疑您的输入文件有 DOS 换行符,导致原始答案给您意外的输出。
      • 太棒了。阿努巴瓦的阿努巴瓦。再次感谢。 :)
      【解决方案4】:

      还有另一种方式,结合 karakfa 的 awk 行,以及使用 GNU wc 来获得最大行长。

      file="./your_file"
      
      awk -v sp=4 -v max="$(wc -L "$file")" '{printf "%-"max+sp"s%s\n",$0,"abcd"}' "$file"
      

      -v 选项将变量 max 初始化为文件中的最大行长度,sp 用于在最大行长度之后使用的空格数。

      输出:

      4044046160710301740053062257440    00000003088 850052246976      MISS WAN         abcd
          046160710301740053062257440    00000003088 850052246976      MISS NISCH       abcd
          046160710301740053062257440    00000003088 850052246976      MISS RACHEL      abcd
      2011888360797600140053062257440    00000009781 851011576287      MR & MRS ROCK    abcd
      

      【讨论】:

      • 嗨,我们这里没有指定位置,是吗?
      • @SanthoshRam:此版本将位置指定为最长行的长度 + 4 。这就是两个-v 选项的作用。
      【解决方案5】:

      我看不出你在哪里卡住了 sed "s/$/ /" test.txtsed "s/.\{80\}/&amp;abcd/" test.txt。 你是如何将它们结合起来的?您不希望 -i 用于第一个命令,这会修改输入文件。 不正确的是

      # error, did you try this:
      sed "s/$/        /" test.txt | sed "s/.\{80\}/&abcd/" test.txt
      

      第二个sed 不会查看第一个命令的输出,而是从原始test.txt 开始。
      您可以将它们(我也使用单引号)与

      sed 's/$/        /' test.txt | sed 's/.\{80\}/&abcd/'
      or shorter
      sed 's/$/        /;s/.\{80\}/&abcd/' test.txt
      

      结果可能看起来不错,但您可以在abcd 之后添加额外的空格。更好的是

      sed -r 's/$/        /;s/(.{80}).*/\1abcd/' test.txt
      

      命令的第一部分很难看。 您可以编写自己的循环,例如

      while IFS= read -r line; do
         printf "%-80sabcd\n" "${line}"
      done < test.txt
      

      这是一个困难的方法,您可以使用@karakfa 给出的简单awk

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-01
        • 2021-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多