【问题标题】:I want to use awk to print rearranged fields then print from the 4th field to the end我想使用 awk 打印重新排列的字段,然后从第 4 个字段打印到末尾
【发布时间】:2017-10-09 19:46:29
【问题描述】:

我有一个包含文件大小、文件日期、文件时间和文件路径记录的文本文件。文件路径可以包含空格并且可以很长(古典音乐名称)。我想用文件日期、文件时间、文件大小和文件路径打印文件。第一部分,没有文件路径很简单:

awk '{print $2,$3,$1}' filelist.txt

这可行,但它会在两行上打印记录:

awk '{print $2,$3,$1,$1=$2=$3=""; print $0}' filelist.txt

我尝试过使用 cut -d' ' -f '2 3 1 4-' ,但这不允许重新排列字段。我可以使用 sed 加入来解决两行问题。一定有办法只使用awk。总之,我想打印第 2 个、第 3 个、第 1 个以及从第 4 个字段到最后。有人可以帮忙吗?

【问题讨论】:

  • edit 您的问题包括简洁、可测试的样本输入和预期输出。
  • 当您尝试在末尾添加$4 时出了什么问题? awk '{print $2, $3, $1, $4}' filelist.txt
  • @leekaiinthesky 正如OP所说,文件路径可能包含空格,因此它不适合$4;相反,它可以传播到不可预测数量的字段$4$5$6 等。考虑一个文件路径C:\Program Files\Common Files\microsoft shared\Team Foundation Server\something——它将分成六个字段!

标签: bash awk


【解决方案1】:

由于awk 中的print statement 总是在最后打印一个换行符(技术上是ORS,默认为换行符),所以您的第一个print 会将输出分成两行。

另一方面,使用printf,您可以使用格式字符串完全控制输出。因此,您可以使用printf(不带换行符)打印前三个字段,然后将它们设置为"",最后使用print $0(相当于不带参数的print)结束:

awk '{ printf("%s %s %s",$2,$3,$1); $1=$2=$3=""; print }' file

【讨论】:

  • 如果$0 是唯一的参数,它是否对print 是必要的? AFAIR print 默认打印 $0,因此单独使用 print 指令就足够了。
  • 你说得对,我已将其添加到我的答案中。谢谢。
【解决方案2】:

我尽可能避免使用 awk。如果我理解正确的话-

while read size date time path
do echo "$date $time $size $path"
done < filelist.txt

您可以printf 而不是echo 以获得更多格式选项。 $path 中的嵌入空格无关紧要,因为它是最后一个字段。

【讨论】:

    【解决方案3】:

    我手头没有awk 可供测试,但我想您可以使用printf 来格式化单行输出。只需在$0 中找到第三个空格,然后从该位置到输入行末尾获取一个子字符串。

    您也可以尝试在标准print 之前交换字段,尽管我不确定它会产生预期的结果...

    【讨论】:

      【解决方案4】:

      &lt;tab&gt;之类的东西来分隔你的字段总是有帮助的,所以后续操作更容易......(我可以看到你使用cut而没有-d,所以你的数据可能已经是制表符分隔了。)

      echo 1 2 3 very long name | 
        sed -e 's/ /\t/' -e 's/ /\t/' -e 's/ /\t/' | 
        awk -v FS='\t' -v OFS='\t' '{print $2, $3, $1, $4}'
      

      第一行生成数据。 sed 命令用\t 替换每行中的前三个空格。然后awk 完美运行,再次输出制表符分隔的数据(你需要一个相当新的awk)。

      【讨论】:

        【解决方案5】:

        使用 GNU awk 进行 gensub():

        $ echo '1 2 3 4 5 6' | awk '{print $3, $2, $1, gensub(/([^ ]+){3}/,"",1)}'
        3 2 1 4 5 6
        

        使用任何 awk:

        $ echo '1 2 3 4 5 6' | awk '{rest=$0; sub(/([^ ]+ ){3}/,"",rest); print $3, $2, $1, rest}'
        3 2 1 4 5 6
        

        【讨论】:

          猜你喜欢
          • 2013-03-13
          • 2018-07-31
          • 2022-01-05
          • 2011-01-06
          • 1970-01-01
          • 2017-06-02
          • 1970-01-01
          • 2011-09-12
          • 2013-02-04
          相关资源
          最近更新 更多