Как извлечь строки из файла, используя их номер строки в Unix?

Используя sed или подобное, как бы вы извлекли строки из файла? Если мне нужны строки 1, 5, 1010, 20503 из файла, как мне получить эти 4 строки?

Что делать, если мне нужно извлечь довольно большое количество строк? Если бы у меня был файл со 100 строками, каждая из которых представляла бы номер строки, которую я хотел извлечь из другого файла, как бы я это сделал?


person monkeyking    schedule 06.01.2010    source источник


Ответы (6)


Что-то вроде "sed -n '1p;5p;1010p;20503p'. Для получения подробностей выполните команду "man sed".

Что касается вашего второго вопроса, я бы преобразовал входной файл в набор команд sed(1) для печати нужных мне строк.

person Steve Emmerson    schedule 06.01.2010
comment
+1, вторую часть ответа нужно искать sed -f - person Michael Krelin - hacker; 07.01.2010

с awk это так же просто, как:

awk 'NR==1 || NR==5 || NR==1010' "file"
person ennuikiller    schedule 06.01.2010
comment
@michael, ерунда, awk тоже может это сделать. - person ghostdog74; 07.01.2010
comment
ennuikiller, да, я в основном комментировал +1 за использование awk в этом контексте, ghostdog74, perl, python, чистый bash и т. д. Это вопрос мнения о правильном инструменте для работы . - person Michael Krelin - hacker; 08.01.2010

@OP, с awk это можно сделать проще и эффективнее. так что на ваш первый вопрос

awk 'NR~/^(1|2|5|1010)$/{print}' file

для 2-го вопроса

awk 'FNR==NR{a[$1];next}(FNR in a){print}' file_with_linenr file
person ghostdog74    schedule 07.01.2010
comment
Второй ответ немного запутан. Чтобы объяснить: FNR==NR произойдет только при чтении file_with_linenr, а не file. В этом случае текст строки добавляется в набор a, а выполнение переходит к следующей строке ввода. Таким образом, при чтении из file применяется только случай (FNR in a), и печатается текст соответствующей строки, если ее номер был помещен в a при разборе file_with_linenr. - person joeln; 08.06.2014

Это некрасиво, и при некоторых обстоятельствах длина команды может превышать ограничения*:

sed -n "$(while read a; do echo "${a}p;"; done < line_num_file)" data_file

Или его гораздо более медленный, но более привлекательный и, возможно, более воспитанный брат:

while read a; do echo "${a}p;"; done < line_num_file | xargs -I{} sed -n \{\} data_file

Вариант:

xargs -a line_num_file -I{} sed -n \{\}p\; data_file

Вы можете немного ускорить версии xarg, добавив параметр -P с каким-нибудь большим аргументом, например, 83 или, может быть, 419 или даже 1177, но 10 выглядит так же хорошо, как и любой другой.

*xargs --show-limits </dev/null может быть поучительным

person Dennis Williamson    schedule 07.01.2010

Я бы исследовал Perl, так как он имеет средства регулярных выражений sed, а также окружающую его модель программирования, позволяющую вам читать файл построчно, подсчитывать строки и извлекать в соответствии с тем, что вы хотите (в том числе из файла номеров строк) .

my $row = 1
while (<STDIN>) {
   # capture the line in $_ and check $row against a suitable list.
   $row++;
}
person Brian Agnew    schedule 06.01.2010
comment
и вы можете использовать perl -e 'perlcode здесь' из командной строки. В Perl также есть оператор диапазона .. как в 3..12, который позволит вам создать список чисел там, где это необходимо. - person Christian V; 07.01.2010
comment
Вы должны использовать $., который автоматически содержит текущий номер строки - person Hasturkun; 07.01.2010
comment
@Hasturkun - не знал этого! Спасибо. - person Brian Agnew; 07.01.2010
comment
Любой, кто интересуется методами командной строки Perl, может захотеть взглянуть на Minimal Perl от Manning... manning.com/maher - person Joe Internet; 07.01.2010

В Перле:

perl -ne 'print if $. =~ m/^(1|5|1010|20503)$/' file
person ire_and_curses    schedule 17.03.2010