Подтвердить что ты не робот

Как читать 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 * 'не является допустимым идентификатором. Любые идеи?

4b9b3361

Ответ 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}