Как вывести $ 1, $ 2, а затем все остальные параметры вместе в AWK - PullRequest
3 голосов
/ 30 мая 2019

Я делаю скрипт, который генерирует псевдонимы / аббревиатуры из базового файла. Базовая структура файла выглядит примерно так:

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"

Но этот код не работает, если в строке много частей после 3-го параметра:

svu    playerctl    -p spotify volume +0.05

Как можно печатать в этом формате? $ 1 $ 2 ($ 3 .. $ N)

Ответы [ 5 ]

2 голосов
/ 30 мая 2019

Вам никогда не понадобится sed, когда вы используете awk. Учитывая этот входной файл:

$ 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"

Выше используется GNU awk для \s и \S - с другими awk вместо [[:space:]] и [^[:space:]].

Поскольку мы используем GNU awk, тем не менее, мы можем сделать работу более кратко и эффективно с помощью 3-го аргумента для 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 голосов
/ 30 мая 2019

Вы можете стереть первые два поля и обрезать пространство от остатка, например.

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

с выводом типа

svu playerctl "-p spotify volume +0.05"

Примечание: регулярное выражение \s требует gnu awk, на что указывает Эд Мортон.

1 голос
/ 30 мая 2019

Вот скрипт 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"
1 голос
/ 30 мая 2019

Заменить два дополнительных поля из существующих.

$ 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 удаляет разделители выходных полей из остатков первых двух полей.

0 голосов
/ 30 мая 2019

Здесь 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, \3.Обратите внимание, что флаг -r используется в приведенной выше команде sed для включения расширенного регулярного выражения.Если этот флаг недоступен на целевом компьютере, то можно использовать следующую команду:

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"

Только различие в двух командах в том, что (, ), + экранируются впотом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...