cmd, вложенный в обратные кавычки, обработанный из sudo?

Чтобы получить первые два столбца вывода:

$ cut -d, -f1 <file | sort | uniq -c | awk -vOFS=, '{ print $2, $1 }'
A,3
B,2
C,2
D,1

Это извлекает первый столбец исходного файла, сортирует его и подсчитывает количество повторяющихся записей. awkв конце просто меняет местами столбцы и вставляет запятую в -между ними.

Последний столбец может быть с

$ sort -u <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }'
2
2
1
1

Это сортирует исходные данные и отбрасывает дубликаты. Затем извлекается первый столбец и подсчитывается количество дубликатов , что . awkв конце извлекает только счетчики.

Комбинируя их с помощью bashиpaste:

$ paste -d, <( cut -d, -f1 <file | sort    | uniq -c | awk -vOFS=, '{ print $2, $1 }' ) \
            <( sort -u <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }' )
A,3,2
B,2,2
C,2,1
D,1,1

Если вы предварительно -отсортируете данные, это может быть немного сокращено (и значительно ускорено):

$ sort -o file file

$ paste -d, <( cut -d, -f1 <file        | uniq -c | awk -vOFS=, '{ print $2, $1 }' ) \
            <( uniq <file | cut -d, -f1 | uniq -c | awk -vOFS=, '{ print $1 }' )
A,3,2
B,2,2
C,2,1
D,1,1
0
22.07.2020, 08:16
1 ответ

`...`и $(...)- это одно и то же с разным синтаксисом, один из оболочки Bourne, другой из оболочки Korn, первый устарел, но все еще поддерживается Bourne -как оболочки для обратной совместимости с древним Bourne. оболочка.

В других оболочках для этого используется другой синтаксис. Например, fishимеет (...), а rc/ esимеет `cmdили `{more complex cmd}или `(sep){cmd}, чтобы указать другое поведение разделения. ksh93и mkshтакже имеют${...; }(вариант без подоболочки ).

В любом случае, это синтаксис языка оболочки, поэтому вам нужна оболочка для его интерпретации и выполнения подстановки команд.

В:

sudo cmd1 `cmd2`

В Борне -как снаряды, оболочка

  • запускает cmd2в дочернем процессе, вывод которого перенаправляется в канал
  • считывает вывод этой команды с другого конца канала,
  • удаляет завершающие символы новой строки,
  • разбивает результат согласно$IFS
  • выполнить генерацию имени файла для результирующих слов (, за исключением zsh; некоторые варианты ksh также выполняют раскрытие фигурных скобок)
  • , а затем передает полученные слова как отдельные аргументы команде sudo, выполняемой в другом дочернем процессе.

sudoзатем меняет uid и запускает команду, которая передается в качестве аргумента.

Если вы хотите, чтобы cmd2запускался с другим uid,вам потребуется sudoдля запуска оболочки для интерпретации кода оболочки, выполняющего подстановку команд:

sudo sh -c 'cmd1 $(cmd2)'
sudo fish -c 'cmd1 (cmd2)'
sudo rc -c 'cmd1 `cmd2'

и так далее.

Обратите внимание, что в Bourne -, как и в оболочках, подстановка команд по-прежнему выполняется в двойных кавычках, поэтому не не:

sudo sh -c "cmd1 $(cmd2)"

Во-первых, это не будет запускать cmd2как root, но также выводcmd2(на этот раз, не подвергнутый разделению + подстановке, поскольку он заключен в кавычки ), будет интерпретироваться как код sh, что обычно представляет собой уязвимость внедрения команд. Например, если cmd2выводит $(reboot), sh, вызванная sudo, будет запрошена интерпретация cmd1 $(reboot)и перезагрузка.

Точно так же не делайтеsudo sh -c 'cmd1 $(cmd2) '"$var"или sudo sh -c 'cmd1 $(cmd2 '"$var"')', если вы хотите передать содержимое переменных вашей оболочки (, а не той, которая запущенаsudocmd1. ] или cmd2. Вместо этого передайте содержимое этих переменных в виде дополнительных аргументов вsh(не внутри кода аргумента )или через переменные среды (, чтобы они стали переменными оболочки. начато sudoа также):

sudo sh -c 'cmd1 $(cmd2) "$1"' sh "$var"
sudo VAR="$var" sh -c 'cmd1 $(cmd2) "$VAR"'

sudo sh -c 'cmd1 $(cmd2 "$1")' sh "$var"
sudo VAR="$var" sh -c 'cmd1 $(cmd2 "$VAR")'

Здесь всегда можно сделать:

sudo cmd1 $(sudo cmd2) "$var"
sudo cmd1 $(sudo cmd2 "$var")

То есть пусть ваша оболочка запускает обе команды с помощью двух отдельных вызовов sudo, чтобы обе запускались с повышенными привилегиями.

Как упоминалось выше, в Bourne -, подобно оболочкам (, но это также относится, хотя и по-другому, к csh -, подобно оболочкам ), подстановка команд без кавычек подлежит разделению + подстановке, поэтому вы оставляйте $(cmd2)без кавычек в cmd1 $(cmd2), только если cmd2выводит список разделенных $IFSшаблонов подстановочных знаков. Если вы хотите, чтобы выводcmd2(без завершающих символов новой строки )передавался целиком как один аргумент в cmd1, вам нужно cmd1 "$(cmd2)"или, что более вероятно, cmd1 -- "$(cmd2)"чтобы убедиться, что аргумент не рассматривается как опция (при условии, что cmd1поддерживает этот --end -of -маркер опции ).

Таким образом, для вашего конкретного варианта использования это будет:

sudo DEVICE="$device" sh -c 'mount -- "$(blkid -u -- "$DEVICE")"'

Или звонить mountтолько в случае успеха blkid:

sudo DEVICE="$device" sh -c '
  output=$(blkid -u -- "$DEVICE") &&
    mount -- "$output"
'
2
18.03.2021, 23:18

Теги

Похожие вопросы