Я пытаюсь получить конкретную строку из текстового файла.
Пока в сети я видел только такие вещи, как sed (я могу использовать только sh -not bash или sed или что-то в этом роде). Мне нужно сделать это только с помощью базового сценария оболочки.
cat file | while read line
do
#do something
done
Я знаю, как перебирать строки, как показано выше, но что, если мне просто нужно получить содержимое определенной строки
cat
нормально, аsed
нет? Это не имеет смысла.cat
. Ой ... милоcat
!Ответы:
sed:
awk:
источник
5!d
означает удалить все строки, кроме 5. Возможна оболочка var, вам нужны двойные кавычки.sed -n 5p
это кажется более логичным для новичков, потому что это-n
означает «без вывода по умолчанию» иp
означает «печать», и нет потенциально сбивающего с толку упоминания об удалении (когда люди говорят о файлах, удаление строк имеет тенденцию означает что-то другое).-n '5p'
работает и с этой проблемой. Разница здесь в том, что5!d
вы можете добавить,-i
чтобы записать изменение обратно в файл. Однако, с-n 5p
вы должныsed -n '5p' f > f2&& mv f2 f
снова, на этот вопрос, я согласен с вашим мнением.Предположим,
line
что это переменная, которая содержит требуемый номер строки, если вы можете использоватьhead
иtail
, тогда это довольно просто:Если нет, это должно сработать:
источник
-eq
сравнение предназначено для целых чисел, поэтому ему нужен номер строки, а не содержимое строки ($line
). Это нужно исправить, определив, например,want=5
до цикла, а затем используя-eq
сравнение$want
. [перенесено из отклоненного редактирования]Вы могли бы использовать
sed -n 5p file
.Вы также можете получить диапазон, например
sed -n 5,10p file
.источник
Лучший метод производительности
Потому что
sed
перестает читать любые строки после пятойОбновленный эксперимент от г-на Роджера Дуэка
источник
sed -n 5q
sed
перестает читать любые строки после 5-й.sed -n 1p /usr/share/dict/words
иsed '1q;d' /usr/share/dict/words
использовалtime
команду; первый занял 0,043 с, второй - всего 0,002 с, так что использование q определенно улучшает производительность!Если, например, вы хотите получить строки с 10 по 20 файла, вы можете использовать каждый из этих двух методов:
или
p
в приведенной выше команде означает печать.Вот что вы увидите:
источник
Стандартный способ сделать это - использовать внешние инструменты. Запрещать использование внешних инструментов при написании сценария оболочки - абсурд. Однако, если вы действительно не хотите использовать внешние инструменты, вы можете распечатать строку 5 с помощью:
Обратите внимание, что будет напечатана логическая строка 5. То есть, если
input-file
содержит продолжения строки, они будут считаться одной строкой. Вы можете изменить это поведение, добавив-r
к команде чтения. (Что, вероятно, является желаемым поведением.)источник
$((++i))
кажется башизмом; если OP ограничен в использовании внешних инструментов, я бы не предполагал, что у них будет доступ к чему-то большему, чем простой/bin/sh
++
приращений специально отмечена как необязательная).$((i+=1))
работает и в Dash.$(($i+1))
это простой обходной путь, о котором я думал.Параллельно с ответом Уильяма Перселла , вот простая конструкция, которая должна работать даже в исходной оболочке Bourne v7 (и, следовательно, также в местах, где Bash недоступен).
Обратите также внимание на оптимизацию
break
выхода из цикла, когда мы получили искомую строку.источник
Мне не особо понравился ни один из ответов.
Вот как я это сделал.
источник
С Perl легко! Если вы хотите получить строки 1, 3 и 5 из файла, скажите / etc / passwd:
источник
seq 5 | perl -ne 'print if $. ~~ [1, 4, 5]'
но smartmatch является экспериментальным, и его использование не рекомендуетсяисточник
sed -n 5p
, которое, конечно, все еще можно оптимизировать до чего-то вродеsed -n '5!d;p;q'