Как передать один элемент из вывода команды в другую команду?

423
jewbix.cube

Базовый пример использования grep (обратите внимание, что grep не будет моим единственным вариантом использования для этого):

$ grep -Irl "foo" path/to/directory/help.js path/to/directory/config.js path/to/directory/task.js 

Теперь я хочу открыть config.jsфайл в Vi. Мой обычный метод будет:

$ vi path/to/directory/config.js 

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

Но я хотел бы иметь возможность просмотреть файл Vi, просто указав, что это второй результат в команде grep. Так что-то вроде:

$ grep -Irl "foo" | xargs vi 2 

Очевидно, что xargs не будет работать так, это был только пример. Но я пытаюсь найти способ использовать xargs (или любую другую утилиту) для достижения этой цели, и я не нахожу его.

То, что товарищ по команде предложил мне, было использовать headи tailвместе, как это:

$ grep -Irl "foo" | tail -n 1 | xargs vi 

получит файл task.js и

$ grep -Irl "foo" | head -n 2 | tail -n 1 | xargs vi 

получит config.js. Хотите знать, если есть менее многословный метод.

3
Выбор по номеру строки кажется странной вещью. Как узнать номер строки, если вы сначала не отображали вывод на терминале? И тогда вы должны считать строки, чтобы выяснить, какой вы хотите. Почему бы не `grep -Irl" foo "путь | grep config`? Barmar 7 лет назад 1
Маловероятно, что я знаю, что `config.js` существует до того, как сделать это, поэтому сначала я просто выполню grep. Затем, когда я вижу файл, с которым я хочу что-то сделать, я нажимаю стрелку вверх, чтобы снова запустить grep и перенаправить результат в то, что откроет файл, который я хочу. Цель состоит в том, чтобы не использовать мою мышь для копирования / вставки пути к файлу. Сотрудник показал мне, что я также могу использовать `screen` для выделения текста в любом месте экрана с помощью клавиатуры. Я понимаю, что это не может сэкономить много времени, особенно если строк слишком много для подсчета, и теперь мне нужно отображать номера строк в моем выводе. jewbix.cube 7 лет назад 0

3 ответа на вопрос

2
nickcrabtree

Не совсем то, о чем просили, потому что он не использует конвейер в vi, а использует sed :

vi $( grep -Irl "foo" | sed -n '2 p')

Ничто не мешает сделать это, добавив в vi - grep -Irl "foo" | sed -n '2 p' | XARGS VI davidgo 7 лет назад 1
Теперь я должен голосовать между использованием sed против awk. Похоже, что awk обычно предпочитают, так как он может делать все, что может sed, и даже больше? Я также предпочитаю метод awk синтаксически. https://stackoverflow.com/questions/1632113/what-is-the-difference-between-sed-and-awk jewbix.cube 7 лет назад 0
1
davidgo

Как насчет

 vi $( grep -IrL "foo" | awk "NR==3" ) 

Это использует AWK, чтобы найти подходящую строку. Выходные данные затем используются в качестве аргумента командной строки для vi.

Я старшеклассник, поэтому я предпочитаю эквивалент, но слегка нахмурился на версию-

 vi ` grep -IrL "foo" | awk "NR==3" ` 
Почему обратная версия более неодобрительна? Еще одно нажатие клавиши для моих целей ... jewbix.cube 7 лет назад 0
Прочитайте https://unix.stackexchange.com/questions/126927/have-backticks-ie-cmd-in-sh-shells-been-deprecated#126928 (и не забудьте поднять голос, если хотите Это !) davidgo 7 лет назад 1
1
mpy

Для этой цели я написал функцию-обертку, которую вы можете использовать, если хотите повторно использовать строку вывода из команды.

Сначала функция для bash :

catch() { out="$($@)"  nl <<< "$out" read -a r -d '\n' <<< "$out" r=("dummy" "$") } 

Тогда для зш :

catch () { out="$($@)"  nl <<< "$out" r=("${(@f)out}")  } 

Использование для обоих вариантов одинаково. Сначала выполните нужную команду с добавлением catch, которая представит вам вывод команды с хорошей нумерацией:

$ catch grep -Irl "foo" 1 path/to/dir/task.js 2 path/to/dir/help.js 3 path/to/dir/config.js $ 

Теперь вы можете повторно использовать любую строку в следующей команде, используя параметр массива $r, например:

$ wc -c $ 14044 path/to/dir/help.js 

В zsh вы можете опустить фигурные скобки ( wc -c $r[2]), но в bash они вам нужны, к сожалению.

Несколько предостережений, которые приходят мне в голову:

  • вывод отображается только после завершения команды
  • странные символы в выводе могут привести к ошибочному поведению (например, перевод строки в имени файла)
  • захватывается только вывод в STDOUT (если какой-то вывод записывается в STDERR, он будет смешан на консоли и проигнорирован $r)

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