Как читать N-ю строку файла и печатать его в новом файле?
У меня есть папка foo. Foo имеет некоторые другие папки, которые могут иметь вспомогательные папки и текстовые файлы. Я хочу найти каждый файл, который начинается с имени года, и читать его N-ю строчку и печатать ее в новом файле. Например, foo имеет файл с именем year1, а в подпапках - файлы с именем year2, year3 и т.д. Программа будет печатать 1-ю строку года1 в файле с именем writeout, после чего она будет печатать вторую строку года2 для записи файла и т.д.
Я также не понимал, как сделать цикл for для файла.
До сих пор я:
#!/bin/bash
for year* in ~/foo
do
Here I tried writing some code using the sed command but I can't think of something else.
done
Я также получаю сообщение в терминале, в котором `year * 'не является допустимым идентификатором.
Любые идеи?
Ответы
Ответ 1
Sed может вам помочь.
Вспомним, что sed обычно обрабатывает все строки в файле И печатает каждую строку в файле.
Вы можете отключить эту функцию и задать только интересующие вас строки, сопоставляя шаблон или номер строки.
Итак, чтобы напечатать 2-ю строку файла 2, вы можете сказать
sed -n '2p' file2 > newFile2
Чтобы напечатать вторую строку, а затем прекратить обработку, добавьте команду q (for quit) (вам также нужны скобки для группировки двух команд), т.е.
sed -n '2{p;q;}' file2 > newFile2
(если вы обрабатываете большие файлы, это может быть довольно экономичным временем).
Чтобы сделать это более общим, вы можете изменить число на переменную, которая будет содержать число, т.е.
lineNo=3
sed -n "${lineNo}{p;q;}" file3 > newFile3
Если вы хотите, чтобы все ваши нарезанные строки вошли в 1 файл, используйте "добавление-перенаправление" оболочки, т.е.
for lineNo in 1 2 3 4 5 ; do
sed -n "${lineNo}{p;q;}" file${lineNo} >> aggregateFile
done
Другие публикации, используя результаты find ...
для управления вашим файловым списком, являются отличным подходом.
Надеюсь, это поможет.
Ответ 2
Вот один из способов сделать это:
awk "NR==$YEAR" $file
Ответ 3
Используйте find
, чтобы найти нужные файлы, а затем sed
, чтобы извлечь то, что вы хотите:
find foo -type f -name year* |
while read file; do
line=$(echo $file | sed 's/.*year\([0-9]*\)$/\1/')
sed -n -e "$line {p; q}" $file
done
Этот подход:
- Используйте
find
для создания списка файлов с именем, начинающимся со строки "год".
- Содержит список файлов в цикле
while
, чтобы избежать длинных командных строк
- Использует
sed
для извлечения искомого номера строки из имени файла
- Использует
sed
для печати только нужной строки, а затем немедленно завершает работу. (Вы можете оставить q
и просто написать ${line}p
, который будет работать, но потенциально менее эффективен $file
, большой. Кроме того, q
может не поддерживаться полностью во всех версиях sed
.)
Он не будет работать должным образом для файлов с пробелами в их именах.
Ответ 4
Лучший способ, который всегда работает, если вы предоставите 2 аргумента:
$ touch myfile
$ touch mycommand
$ chmod +x mycommand
$ touch yearfiles
$ find / -type f -name year* >> yearfiles
$ nano mycommand
$ touch foo
Введите это:
#/bin/bash
head -n $1 $2 >> myfile
less -n 1 myfile >> foo
Используйте ^X
, y
и введите для сохранения. Затем запустите mycommand:
$ ./mycommand 2 yearfiles
$ cat foo
year2
Предполагая, что ваши файлы year
:
year1, year2, year3
Кроме того, теперь у вас есть настройка, вам просто нужно использовать $ ./mycommand LINENUMBER FILENAME
с этого момента.
Ответ 5
В вашей задаче есть две подзадачи: найдите имя всех файлов года, а затем извлеките N-ю строку. Рассмотрим следующий script:
for file in `find foo -name 'year*'`; do
YEAR=`echo $file | sed -e 's/.*year\([0-9]*\)$/\1/'`
head -n $YEAR $file | tail -n 1
done
Вызов find находит соответствующие файлы для вас в каталоге foo. Вторая строка извлекает только цифры в конце имени файла из имени файла. Третья строка затем извлекает первые N строк из файла, сохраняя только последнюю из первых N строк (чтение: только N-я строка).
Ответ 6
1.time head -5 emp.lst tail -1
It has taken time for execution is
real 0m0.004s
user 0m0.001s
sys 0m0.001s
or
2.awk 'NR==5' emp.lst
It has taken time for execution is
real 0m0.003s
user 0m0.000s
sys 0m0.002s
or
3.sed -n '5p' emp.lst
It has taken time for execution is
real 0m0.001s
user 0m0.000s
sys 0m0.001s
or
4.using some cute trick we can get this with cut command
cut -d "
" -f 5 emp.lst
# after -d press enter ,it means delimiter is newline
It has taken time for execution is
real 0m0.001s
Ответ 7
Здесь вы идете
sed ${index}'q;d' ${input_file} > ${output_file}