1

Я использую следующий код для извлечения информации из набора текстовых файлов (foo * .txt).

for file in foo*.txt; do 
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar.csv
done

Этот комментарий печатает нужные мне числа из набора файлов (foo * .txt). Когда я пытаюсь напечатать как имя файла (в одном столбце файла CSV), так и номер (в следующем столбце файла CSV), я попытался выполнить следующие действия в Терминале.

for file in foo*.txt; do 
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar2.csv 
done

Это печатает имена файлов в терминале. Файл CSV содержит числа, которые я хочу. Как этот код можно изменить, чтобы имя файла было напечатано в одной колонке, а извлеченные числа - в следующей колонке файла CSV?

Другая проблема в этом коде - это проблема сортировки. Например, рассмотрим имена файлов foo_01_s.txt, foo_02_s.txt, foo_03_s.txt ..... foo_100_s.txt. Если я хочу извлечь информацию (используя комментарии выше), последний файл (foo_100_s.txt) не идет после foo_99_s.txt.

Решение с использованием Python/Perl также было бы полезно.

1 ответ1

2

Вы должны понимать, что >> будет перенаправлять только часть текущей команды - в основном это просто число, которое является результатом команды, начинающейся с grep и переданной несколько раз. echo $file - это отдельная команда (вы используете ;), и поэтому она обычно направляется в стандартный вывод. Все, что вам нужно сделать, это перенаправить после всего цикла:

for file in foo*.txt; do 
    echo $file
    grep "some_text" $file | tail -n5 | awk '{print $2}'
done > bar2.csv

Если вы хотите "версию" отсортировать ваши файлы (это подходящее имя), вы можете перечислить их после сортировки:

for file in $(ls foo*.txt | sort -V); do

для быстрого запуска чего-нибудь маленького (несколько минут для ~ 1000 файлов) это должно быть хорошо.

РЕДАКТИРОВАТЬ

После вашего комментария есть несколько решений. Я предполагаю, что вы хотите:

file1 1
      2
      3

и т.д. Просто отбросьте echo и измените строку эха:

for file in foo*.txt; do 
    grep "some_text" $file | tail -n5 | awk -v f=$file '{if(NR==1) {printf("%-20s %-5s\n",f,\$2)} else {printf("%-20s %-5s\n","",$2)}}'
done > bar2.csv

Я позволил awk сделать печать для меня. Использование -v позволяет мне передать переменную в f . Для печати ознакомьтесь с синтаксисом printf (вы можете использовать man printf в оболочке. В основном я предполагаю два поля, одно с 20, другое 5 и пробел между ними. Отрицательный знак слева оправдывает. Вы можете играть с этим. Это решило бы вашу первоначальную проблему, так как теперь вы можете передать эту строку.

Если вы хотите, чтобы файл просто был:

file1,1
file1,2
...
file2,1

вы можете либо опустить if в моем выражении awk , либо оставить исходное решение с помощью echo, но использовать,

echo -n "$file,"

где -n гарантирует отсутствие новой строки.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .