如何在AWK中一起打印$ 1,$ 2和所有其余参数

时间:2019-05-30 11:59:17

标签: shell awk sed

我正在编写一个从基本文件生成别名/缩写的脚本。基本文件结构是这样的:

sctl   sudo         systemctl
pac    sudo         pacman

这与下面的代码可以正常工作,该代码读取基本文件,删除注释并在缩写文件上添加缩写行:

    sed "s/\s*#.*$//;/^\s*$/d" $command_file | 
    awk -v c=$cmd -v o="$comp" '{ print c" "$1""o"\""$2" "$3"\"" }' >> $file

最终结果将是这样:

abbr sctl "sudo systemctl"
abbr pac "sudo pacman"

但是当该行在第三个参数之后包含很多部分时,此代码将不起作用:

svu    playerctl    -p spotify volume +0.05

如何进行这种格式的打印? $ 1 $ 2($ 3 .. $ N)

5 个答案:

答案 0 :(得分:2)

您可以删除前两个字段,并从其余部分中修剪空间,例如。

{ 
  printf "%s %s ", $1, $2
  $1=$2=""; sub(/^\s*/, "", $0);
  printf "\"%s\"\n", $0
}

输出类似,

svu playerctl "-p spotify volume +0.05"

注意:\s正则表达式需要Ed Morton指出的gnu awk。

答案 1 :(得分:2)

使用awk时,您永远不需要sed。给定此输入文件:

$ cat file
sctl   sudo         systemctl   # here is a comment
        # and here is another
pac    sudo         pacman

svu    playerctl    -p spotify volume +0.05

这是您的sed + awk输出:

$ sed "s/\s*#.*$//;/^\s*$/d" file |  awk -v c="abbr" -v o=" " '{ print c" "$1""o"\""$2" "$3"\"" }'
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
abbr svu "playerctl -p"

您可以单独从awk获得

$ awk -v c="abbr" -v o=" " '{sub(/\s*#.*/,"")} NF{print c" "$1""o"\""$2" "$3"\""}' file
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
abbr svu "playerctl -p"

,然后您可以对其进行调整以执行所需的操作:

$ awk -v c="abbr" -v o=" " '{sub(/\s*#.*/,"")} NF{x=$1; sub(/^\S+\s+/,""); $1=$1; print c, x o "\"" $0 "\""}' file
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
abbr svu "playerctl -p spotify volume +0.05"

或(从您的问题中我无法分辨出您想要在双引号内/外使用什么):

$ awk -v c="abbr" -v o=" " '{sub(/\s*#.*/,"")} NF{x=$1" "$2; sub(/^(\S+\s+){2}/,""); $1=$1; print c, x o "\"" $0 "\""}' file
abbr sctl sudo "systemctl"
abbr pac sudo "pacman"
abbr svu playerctl "-p spotify volume +0.05"

上面的\s\S使用GNU awk-其他awks则使用[[:space:]][^[:space:]]

但是,由于我们使用的是GNU awk,所以我们可以使用第三个arg来match()来更简洁,更高效地完成工作:

$ awk -v c="abbr" -v o=" " '{sub(/\s*#.*/,""); $1=$1} match($0,/(\S+) (.*)/,a){print c, a[1] o "\"" a[2] "\""}' file
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
abbr svu "playerctl -p spotify volume +0.05"

$ awk -v c="abbr" -v o=" " '{sub(/\s*#.*/,""); $1=$1} match($0,/(\S+ \S+) (.*)/,a){print c, a[1] o "\"" a[2] "\""}' file
abbr sctl sudo "systemctl"
abbr pac sudo "pacman"
abbr svu playerctl "-p spotify volume +0.05"

答案 2 :(得分:1)

用另外两个字段替换掉。

$ echo "svu playerctl -p spotify volume +0.05" | gawk '
  { print $1; $1 = ""
    print $2; $2 = ""
    print substr($0,3) } '
svu
playerctl
-p spotify volume +0.05

substr从前两个字段的残余中删除输出字段分隔符。

答案 3 :(得分:1)

这是一个awk(标准Linux-特定于gawk)脚本,一次完成所有工作:

awk -v c="abbr" -v o=" " '/(^\s*$)|(^\s*#.*$)/ {next}  # discard empty lines and comments
{
    arg3=$0;                          # save current line to arg3 variable
    sub($1" "$2,"",arg3);             # remove $1  and $2 from arg3
    print(c" "$1""o"\""$2" "arg3"\"") # print formated output
}' input.txt

input.txt

ctl   sudo         systemctl
# comment line
pac    sudo         pacman
   # comment line
demo1  sudo         arg1 arg2 arg3

demo2  sudo         arg4 -arg5 -arg6 456
                         # comment line

输出:

abbr ctl "sudo          systemctl"
abbr pac "sudo          pacman"
abbr demo1 "sudo          arg1 arg2 arg3"
abbr demo2 "sudo          arg4 -arg5 -arg6 456"

答案 4 :(得分:0)

这是GNU sed版本:

sed -r 's/(^[^ ]+)\s+([^ ]+)\s+(.*)/abbr \1 "\2 \3"/g' base_file
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
abbr svu "playerctl -p spotify volume +0.05"

说明: :这里使用了反向引用,每一列都被捕获到各自的组中,并随后用作\1\2,{ {1}}。请注意,上述sed命令中使用\3标志来启用扩展的正则表达式。如果该标志在目标计算机上不可用,则可以使用以下命令:

-r

这两个命令的唯一区别在于,sed 's/\(^[^ ]\+\)\s\+\([^ ]\+\)\s\+\(.*\)/abbr \1 "\2 \3"/g' base_file abbr sctl "sudo systemctl" abbr pac "sudo pacman" abbr svu "playerctl -p spotify volume +0.05" ()在稍后被转义。