【问题标题】:AWK command to print until end of lineAWK 命令打印到行尾
【发布时间】:2013-06-10 02:24:18
【问题描述】:

我有一个关于 AWK 命令的简短问题。我需要命令打印到同一行的行尾,但是当它到达下一行时,我需要它在另一行上打印。以下示例将提供更好的清晰度。

假设我有一个文件:

0 1 2 3 This is line one
0 1 2 3 This is line two 
0 1 2 3 This is line three 
0 1 2 3 This is line four

我已经尝试了以下并得到了以下结果

awk '{for(i=5;i<=NF;i++) print $i}' fileName >> resultsExample1

我在 resultsExample1 中得到以下信息

This
is
line
one
This 
is 
line 
two 
And so on....

示例 2:

awk 'BEGIN {" "} {for(i=5;i<=NF;i++) printf $1}' fileName >> resultsExample2

对于 resultsExample2 我得到:

This is line one This is line two this is line three This is line four

我也试过了:

awk 'BEGIN {" "} {for(i=5;i<=NF;i++) printf $1}' fileName >> resultsExample3

但是结果和上一个一样

最后我想要的是:

This is line one
This is line two 
This is line three
This is line four

感谢您的帮助! 在此先感谢:)

【问题讨论】:

  • 在示例中,所有行都有相同的列数 - 您的输入总是这样吗?

标签: shell unix awk


【解决方案1】:

我知道这个问题很老了,但是另一个 awk 例子:

awk '{print substr($0,index($0,$5))}' fileName

它的作用: 找到要开始打印的索引($0 中的 $5 索引)并从该索引开始打印 $0 的子字符串。

【讨论】:

  • 如果$5 具有在先前字段中找不到的值,则它可以工作。如果是这种情况(对我来说是:-),我认为这是最易读的解决方案。
  • 这在我们处理块级别(而不是行)时非常有用:top -1 -bSHEk -u yarn | awk -v RS='top - ' -v FS='\n' '{print substr($0,index($0,$14))}' 会很好地打印单个块中您想要的行之后的每一行!
  • 危险。正如@MatM 暗示的那样,如果字段 1 到 4 之一与字段 5 相同,则此解决方案将失败。考虑此输入 a man a plan a canal panama
【解决方案2】:

使用cut 可能更直接:

$ cut -d' ' -f5- file
This is line one
This is line two 
This is line three 
This is line four

这表示:在空格分隔的字段上,从第 5 行打印到行尾。

如果您碰巧在字段之间有多个空格,您最初可能希望使用tr -s' ' 压缩它们。

【讨论】:

  • 这只有在字段之间只有一个空格时才有效。
  • 没错,@Scrutinizer,但如果有多个空格,我们可以先通过管道| tr -s ' ' 删除多个空格。
  • 如果空格(分隔符)的数量从一条记录到另一条记录不同,您将如何处理?例如将此应用于ls -l的输出?
  • @gone 我应该更详细地看到这个,但是parsing ls is not a good idea
  • @fedorqui,我并不是要把话题转移到解析ls 是否是一个好主意的话题上。关键是在某些输出中,分隔符可以是弹性的。
【解决方案3】:

用 awk 或

awk '{$1=$2=$3=$4=""; sub(/^  */,"", $0); print }'  awkTest2.txt
This is line one
This is line two
This is line three
This is line four

另外,你的解决方案几乎就在那里,你只需要强制在每个处理行的末尾打印一个 '\n',即

awk '{for(i=5;i<=NF;i++) {printf $i " "} ; printf "\n"}' awkTest2.txt
This is line one
This is line two
This is line three
This is line four

请注意,您的 BEGIN { " " } 是禁止操作。你应该使用$i 而不是$1 来打印当前的迭代值。

IHTH。

编辑 ;注意到 sudo_O 反对,我在数据中添加了 %s。这是输出

This is line one
This is line two
This is line three
T%shis is line four

这对您来说可能是个问题,因此请阅读有关如何将格式字符串传递给 printf 的案例。

【讨论】:

  • 您不应该在未指定格式的情况下使用printf。例如,如果其中一个字段包含%s,您认为会发生什么?
  • 我同意 sudo_O。例如,您应该得到awk: not enough args in printf(T%shis )..
  • 我正在弥补我的输出。祝大家好运。
  • 感谢您也为我提供了使用 awk 的解决方案!
【解决方案4】:

awk '{gsub (/[[:digit:]]/,"");{$1=$1}}1' file

【讨论】:

    【解决方案5】:

    sed 为这个问题提供了最佳解决方案

    公认的基于剪切的解决方案的问题是,与 awk 不同,它假定字段之间恰好有一个空格。

    使用tr -s ' ' 将多个相邻空格压缩到一个空格中的通常解决方法也是有问题的:它会折叠行尾剩余部分的空格,从而修改它,正如@inopinatus 评论的那样。

    以下基于 sed 的解决方案将实现我们的目标,同时在行的其余部分保留空格:

    sed -E 's/^([^ \t]*[ \t]*){4}//' <<'EOF'
    0 1 2 3 This is line one
    0 1 2 3 This is line two   test of extra spaces
    0 1 2 3 This is line three
    0 1 2 3 This is line four
    EOF
    

    结果:

    This is line one
    This is line two   test of extra spaces
    This is line three
    This is line four
    

    我们模拟了 awk 以空格序列分隔字段的默认行为。

    字段通常由空格序列(空格、制表符和换行符)分隔
    Default Field Splitting (The GNU Awk User’s Guide)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 1970-01-01
      • 2014-04-04
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      • 2022-01-13
      相关资源
      最近更新 更多