Команда для получения n-й строки стандартного вывода
Вопрос
Есть ли какая-нибудь команда bash, которая позволит вам получить n-ю строку стандартного вывода?
То есть что-то, что заняло бы это
$ ls -l
-rw-r--r--@ 1 root wheel my.txt
-rw-r--r--@ 1 root wheel files.txt
-rw-r--r--@ 1 root wheel here.txt
и сделайте что-нибудь вроде
$ ls -l | magic-command 2
-rw-r--r--@ 1 root wheel files.txt
Я понимаю, что это было бы плохой практикой при написании сценариев, предназначенных для повторного использования, НО при повседневной работе с оболочкой мне было бы полезно иметь возможность фильтровать мой стандартный вывод таким образом.
Я также понимаю, что это была бы полутривиальная команда для записи (buffer STDOUT, возвращает определенную строку), но я хочу знать, есть ли какие-то стандартный команда оболочки для выполнения этого, которая была бы доступна без того, чтобы я вставлял скрипт на место.
Решение
Использование sed
, только для разнообразия:
ls -l | sed -n 2p
Использование этой альтернативы, которая выглядит более эффективной, поскольку она прекращает чтение ввода при печати требуемой строки, может генерировать SIGPIPE в процессе подачи, что, в свою очередь, может генерировать нежелательное сообщение об ошибке:
ls -l | sed -n -e '2{p;q}'
Я видел это достаточно часто, так что обычно я использую первое (что легче вводить в любом случае), хотя ls
- это не команда, которая жалуется, когда получает SIGPIPE.
Для диапазона строк:
ls -l | sed -n 2,4p
Для нескольких диапазонов строк:
ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'
Другие советы
ls -l | head -2 | tail -1
Альтернатива хорошему способу "голова / хвост":
ls -al | awk 'NR==2'
или
ls -al | sed -n '2p'
Ради полноты; -)
более короткий код
find / | awk NR==3
короче жизнь
find / | awk 'NR==3 {print <*>; exit}'
Попробуйте эту sed
версию:
ls -l | sed '2 ! d'
Там написано "удалить все строки, которые не являются вторыми".
Вы можете использовать awk:
ls -l | awk 'NR==2'
Update
Приведенный выше код не получит то, что мы хотим, из-за ошибки «один на один»: первая строка команды ls -l - это строка total . Для этого будет работать следующий пересмотренный код:
ls -l | awk 'NR==3'
Легко ли вам доступен Perl?
$ perl -n -e 'if ($. == 7) { print; exit(0); }'
Очевидно, замените любое число на 7.
Предложен другой постер
ls -l | head -2 | tail -1
но если вы направите трубку в хвост, похоже, что все, вплоть до строки N, обрабатывается дважды.
Трубка хвостом в голову
ls -l | tail -n +2 | head -n1
будет более эффективным?
Да, самый эффективный способ (как уже указывал Джонатан Леффлер) - это использовать sed с print & amp; бросить курить:
set -o pipefail # cf. help set
time -p ls -l | sed -n -e '2{p;q;}' # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}" # cf. man bash | less -p 'PIPESTATUS'
Хммм
sed в моем случае не сработал.Я предлагаю:
для "нечетных" строк 1,3,5,7...ls |awk '0 == (NR+1) % 2'
для "четных" строк 2,4,6,8 ls |awk '0 == (NR) % 2'
Для большей полноты.
ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)
Выбрасывайте строки, пока не дойдете до второй, затем распечатайте первую строку после этого. Итак, он печатает 3-ю строку.
Если это просто вторая строка ..
ls -l | (read; head -n1)
Положите столько прочитанных, сколько необходимо.
Я добавил это в свой .bash_profile
function gdf(){
DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk '{print $4}')
SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk '{print $2}')
git show $SHA -- $DELETE_FILE_PATH
}
И это работает
gdf <file name>