Передайте вывод предыдущей команды к затем как аргумент

Это - то, как я закончил тем, что делал его.

Я создал файл /etc/sudoers.d/dev

Содержа:

# allow user dev to become user tomcat
# invoked with [dev@host ~]$ sudo su - tomcat
dev ALL = (root) NOPASSWD: /bin/su - tomcat

измененный полномочия файла с chmod 0440 /etc/sudoers.d/dev

созданный псевдоним в dev's .bashrc alias tomcat='sudo su - tomcat'

Это приводит к способности к dev пользователю стать пользователем кота или без имеющий необходимость ввести (или без действительно имеющий) пароль когда-либо путем ввода tomcat в командной строке.

130
11.01.2014, 01:35
7 ответов

Вы путаете два совсем других типа исходных данных.

  1. Стандартный вход (stdin)
  2. Параметры командной строки

Они отличаются, и полезны для различных целей. Некоторые команды могут взять вход обоими способами, но они обычно используют их по-другому. Возьмите, например, wc команда:

  1. Проходить мимо входа stdin:

    ls | wc -l
    

    Это будет считать строки в выводе ls

  2. Передача, введенная параметрами командной строки:

    wc -l $(ls)
    

    Это будет считать строки в списке файлов распечатанными ls

Совершенно другие вещи.

Для ответа на вопрос это кажется, что Вы хотите получить уровень от вывода первой команды и затем использовать уровень в качестве параметра командной строки для второй команды. Вот один способ сделать это:

rate=$(command1 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p')
command2 -t "rate was $rate"

Объяснение sed:

  • s/pattern/replacement/ команда должна заменить некоторый шаблон
  • Средства шаблона: строка должна запуститься с "уровня" (^rate) сопровождаемый любыми двумя символами (..), сопровождаемый 0 или больше цифрами, сопровождаемыми a %, сопровождаемый остальной частью текста (.*)
  • \1 в замене означает контент первого выражения, полученного в \(...\), так в этом случае цифры перед % знак
  • -n флаг sed управляйте средствами не распечатать строки по умолчанию. p в конце s/// управляйте средствами распечатать строку, если была замена. Короче говоря, команда распечатает что-то, только если было соответствие.
150
27.01.2020, 19:29

Моделировать вывод command1 Я использую этот оператор эха:

$ echo -e "Foo\nrate (10%) - name: value - 10Kbps\nBar"
$ alias command1='echo -e "Blah\nrate (10%) - name: value - 10Kbps\nBlag"'

Быстрый тест:

$ command1
Blah
rate (10%) - name: value - 10Kbps
Blag

Это - вся польза, поэтому позволяет, анализируют его:

$ command1 | grep 'rate'
rate (10%) - name: value - 10Kbps

Таким образом, мы получаем строку, мы хотим из command1, позволяет передаче это в command2:

$ alias command2='echo'
$ command2 -t="rate was "$(command1 | grep 'rate')
-t=rate was rate (10%) - name: value - 10Kbps

Я ожидаю "rate was "$(command1 | grep 'rate') конкатенировать автоматически. Если это не работает из-за пробела, необходимо смочь передать вход как так вместо этого:

$ alias command2='echo'
$ command2 -t=$(echo '"rate was ' $(command1 | grep 'rate') '"')
-t="rate was rate (10%) - name: value - 10Kbps "
4
27.01.2020, 19:29

Попробуйте это использование и :

command | grep -oP '\$>\s+rate\s+\(\K[^\)]+'
3
27.01.2020, 19:29

Первая задача состоит в том, чтобы извлечь уровень из той строки. С GNU grep (не встроил Linux или Cygwin), можно использовать -o опция. Часть, которую Вы хотите, является одной содержащей только цифры, и сопровождаемый a % знак. Если Вы не хотите извлекать % самостоятельно, Вам нужен дополнительный прием: утверждение предвидения нулевой ширины, которое соответствует только, только если это ничто не сопровождается %.

command1 -p=aaa -v=bbb -i=4 | grep -o -P '[0-9]+(?=%)'

Другая возможность состоит в том, чтобы использовать sed. Для извлечения части строки в sed используйте s команда, с regex, который соответствует целой строке (запускающийся с ^ и окончание $), с частью для сохранения в группе (\(…\)). Замените целую строку содержанием группы (групп) для хранения. В целом передайте -n опция выключить печать по умолчанию и поместить p модификатор для печати строк, где существует что-то для извлечения (здесь существует одна строка, таким образом, это не имеет значения). Посмотрите Возврат только часть строки после шаблона соответствия и Извлечения regex, соответствовавшего 'sed', не печатая окружающие символы для большего количества приемов sed.

command1 -p=aaa -v=bbb -i=4 | sed 's/^.*rate(\([0-9]*\)%).*$/\1/'

Более гибкий снова, чем sed, awk. Awk выполняет инструкции для каждой строки на маленьком императивном языке. Существует много способов извлечь уровень здесь; я выбираю вторые поля (поля разграничены пробелом по умолчанию), и удалите все символы в нем, которые не являются цифрой.

command1 -p=aaa -v=bbb -i=4 | awk '{gsub(/[^0-9]+/, "", $2); print $2}'

Следующий шаг, теперь, когда Вы извлекли уровень, должен передать его как аргумент command2. Инструмент для этого является командой susbtitution. Если Вы вставляете команду $(…) (долларовая круглая скобка), ее выводом заменяют в командную строку. Вывод команды разделяется на отдельные слова в каждом пробельном блоке, и каждое слово рассматривают как подстановочный шаблон; если Вы не хотите, чтобы это произошло, поместите двойные кавычки вокруг замены команды: "$(…)". С двойными кавычками вывод команды используется непосредственно в качестве единственного параметра (единственное преобразование состоит в том, что новые строки в конце вывода удалены).

command2 -t "$(command1 -p=aaa -v=bbb -i=4 |
               sed 's/^.*rate(\([0-9]*\)%).*$/\1/')"
2
27.01.2020, 19:29

Можно использовать grep и это - PCRE - Perl Совместимые Регулярные выражения. Это позволяет Вам использовать lookbehind для соответствия значению уровня без включения строки "уровень" в результатах при захвате для него.

Пример

$ echo "rate (10%) - name: value - 10Kbps" | grep -oP '(?<=^rate \()\d+'
10

Подробнее

Вышеупомянутое grep работы следующим образом:

  • -o возвратит только, что мы ищем, \d+, который является цифрами в parens.
  • -P активирует опцию PCRE grep
  • (?<=^rate \() будет только возвращаемые строки, которые начинаются "с уровня ("

command2

Для ловли значения "уровня", можно работать command1 как так:

$ rate=$(command 1 | grep -oP '(?<=^rate \()\d+'

Затем для Вашей 2-й команды Вы просто использовали бы ту переменную.

$ command2 -t=${rate}

Вы могли стать необычными и сделать ту всю одну строку:

$ command2 -t=$(command1 | grep -oP '(?<=^rate \()\d+')

Это выполнит command1 в $(..) блок выполнения, возьмите его результаты и включайте их в command2 -t=.. переключатель.

0
27.01.2020, 19:29

Обычно я использую это:

command1 | xargs -I{} command2 {}

Передайте вывод command1через xargs, заменив (фигурные скобки )на command2. Если команда1 равна find, обязательно используйте -print0и добавьте -0к xargsдля строк с завершающим нулем, а xargsбудет вызывать command2для каждой найденной вещи.

В вашем случае (и взятие строки sed от @Janos):

command1 -p=aaa -v=bbb -i=4 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p' | xargs -I{} command2 -t="rate was {}"
70
27.01.2020, 19:29

Обычно я использую `команду `, чтобы поместить ее вывод в качестве аргумента другой команды. Например, чтобы найти ресурсы, потребляемые процессом foo на freebsd, будет:

procstat -r `pgrep -x foo`

Здесь pgrep используется для извлечения PID процесса foo, который передается команде procstat, которая ожидает PID процесса в качестве аргумента.

3
27.01.2020, 19:29

Теги

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