[英]How to print $1, $2 and then all remaining parameters together in AWK
I'm making a script that generates aliases/abbreviations from a base file. 我正在创建一个从基本文件生成别名/缩写的脚本。 The base file structure is something like this: 基本文件结构是这样的:
sctl sudo systemctl
pac sudo pacman
This works fine with the following code that reads the base file, removes comments and awks the abbreviation line on the abbreviation file: 这适用于下面的代码,它读取基本文件,删除注释并解释缩写文件中的缩写行:
sed "s/\s*#.*$//;/^\s*$/d" $command_file |
awk -v c=$cmd -v o="$comp" '{ print c" "$1""o"\""$2" "$3"\"" }' >> $file
And the end result would be something like this: 最终结果将是这样的:
abbr sctl "sudo systemctl"
abbr pac "sudo pacman"
But this code doesn't work when the line has many parts after the 3rd parameter: 但是当第3个参数后行有很多部分时,此代码不起作用:
svu playerctl -p spotify volume +0.05
How can i go about printing in that format? 我怎样才能以这种格式打印? $1 $2 ($3..$N) $ 1 $ 2($ 3 .. $ N)
You can erase the first two fields and trim the space from the remainder, eg. 您可以擦除前两个字段并从剩余部分修剪空间,例如。
{
printf "%s %s ", $1, $2
$1=$2=""; sub(/^\s*/, "", $0);
printf "\"%s\"\n", $0
}
With output like, 输出像,
svu playerctl "-p spotify volume +0.05"
Note: the \\s
regex requires gnu awk as pointed out by Ed Morton. 注意: \\s
正则表达式需要Ed Morton指出的gnu awk。
You never need sed when you're using awk. 当你使用awk时,你永远不需要sed。 Given this input file: 给定此输入文件:
$ cat file
sctl sudo systemctl # here is a comment
# and here is another
pac sudo pacman
svu playerctl -p spotify volume +0.05
here's what your sed+awk outputs: 这是你的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"
which you can get just from awk alone: 你可以从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"
and which you can then adjust to do what you want: 然后您可以调整以执行您想要的操作:
$ 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"
or (I can't tell from your question what you want inside/outside of the double quotes): 或者(我无法从你的问题中告诉你在双引号内/外的内容):
$ 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"
The above uses GNU awk for \\s
and \\S
- with other awks use [[:space:]]
and [^[:space:]]
instead. 以上使用GNU awk for \\s
和\\S
- 与其他awks使用[[:space:]]
和[^[:space:]]
代替。
Since we're using GNU awk, though, we can do the job more concisely and efficiently with the 3rd arg to match(): 既然我们正在使用GNU awk,那么我们可以通过第3个arg来更简洁有效地完成工作来匹配():
$ 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"
Substitute the two extra fields out of existence. 替换两个额外的字段不存在。
$ 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
The substr
removes the output field separators from the remnants of the first two fields. substr
从前两个字段的残余中删除输出字段分隔符。
Here is an awk (standard Linux - specific to gawk) script that does all the work in one sweep: 这是一个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 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
Output: 输出:
abbr ctl "sudo systemctl"
abbr pac "sudo pacman"
abbr demo1 "sudo arg1 arg2 arg3"
abbr demo2 "sudo arg4 -arg5 -arg6 456"
Here is GNU sed
version: 这是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"
Explanation: Here back-referencing is used, each column is captured into respective groups and later used as \\1
, \\2
, \\3
. 说明:此处使用反向引用,每列被捕获到相应的组中,稍后用作\\1
, \\2
, \\3
。 Note that -r
flag is used in above sed command to enable extended regex. 请注意,在上面的sed命令中使用-r
标志来启用扩展的正则表达式。 If this flag is not available in the target machine, then following command can be used: 如果目标计算机中没有此标志,则可以使用以下命令:
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"
Only difference in the two commands in that (
, )
, +
are escaped in the later. 只有(
, )
, +
中的两个命令的差异在后面被转义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.