Добавление столбца значений в файл с разделителями табуляции

17

Как я могу добавить столбец значений в файл, который имеет определенное количество строк. У меня есть входной файл, как это:

Входной файл:

SPATA17 1   217947738
LYPLAL1 1   219383905
FAM47E  4   77192838
SHROOM3 4   77660162
SHROOM3 4   77660731
SHROOM3 4   77662248

Выходной файл:

SPATA17 1   217947738 file1
LYPLAL1 1   219383905 file1
FAM47E  4   77192838  file1
SHROOM3 4   77660162  file1
SHROOM3 4   77660731  file1
SHROOM3 4   77662248  file1

В этом случае я хочу добавить Столбец значений до количества строк в файле. Значение остается неизменным, например «file1».

Причина в том, что у меня есть 100 таких файлов. Я не хочу открывать каждый файл и вставлять столбец. Также есть ли способ автоматизировать это, перейдя в каталог и добавив столбец значений. Значение берется из имени файла, которое должно быть добавлено в каждую строку файла в последнем / первом столбце.

Рон
источник

Ответы:

22

Вы можете использовать однолинейный цикл следующим образом:

for f in file1 file2 file3; do sed -i "s/$/\t$f/" $f; done

Для каждого файла в списке это будет использоваться sedдля добавления в конец каждой строки вкладки и имени файла.

Объяснение:

  • Использование -iфлага с sedдля выполнения замены на месте, перезаписи файла
  • Выполните замену с помощью s/PATTERN/REPLACEMENT/. В этом примере PATTERN - $это конец строки, а REPLACEMENT - это \t(= TAB) и $fэто имя файла из переменной цикла. Команда s///находится в двойных кавычках, так что оболочка может раскрывать переменные.
Янош
источник
Код работает. Можете ли вы объяснить содержание в кавычках?
Рон
Так же, как «awk» используется при работе со столбцами, «sed» также используется для аналогичных ситуаций. Я новичок в «awk» и «sed».
Рон
@Ron sedнаиболее удобен для замены шаблонов и сохранения на месте. Для вашего требования сохранения файла это был относительно удобный вариант. Если вам не нужно записывать обратно в тот же файл, который вы обрабатываете, то awkобычно с ним гораздо проще работать.
Janos
Лично меня awkслишком часто отключают входные / выходные разделители полей, поэтому я стараюсь по возможности избегать его использования, делая его sedболее привлекательным.
user5359531
11

Давай, почему вы, ребята, рекомендуете эти мощные инструменты, когда есть pasteкоманда!

$ cat a
A
B
C
D
$ cat b
1
2
3
4
$ paste a b
A   1
B   2
C   3
D   4

С небольшой хитростью, вы можете использовать pasteдля целей ОП. Тем не менее, он не заменит файлы на месте:

for f in file1 file2 file3; do 
    paste $f <(yes $f | head -n $(cat $f | wc -l)) > $f.new
done

Это вставит соответствующее имя файла в качестве последнего столбца каждого файла в новый файл filename.new

yegle
источник
Благодарность! pasteбезусловно, скрытый драгоценный камень.
neu242
10

Вы можете использовать awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...
cuonglm
источник
Поскольку у каждого файла свое имя, я должен сделать это 100 раз. Есть ли способ сделать это один раз?
Рон
Нет, FILENAMEэто переменная awk, она расширяется до текущего имени файла, который awkобрабатывается. Вы просто делаете это один, кормить все файлы awk.
cuonglm
Хорошо, но как направить вывод в новый файл каждого файла? Сохраняет ли awk каждый файл при обработке?
Рон
Если у вас есть GNU awk 4.1.0или позже, вы можете использовать -iдля редактирования на месте. В противном случае вы должны перенаправить awkвывод в временный файл, а затем использовать grepдля извлечения строки из каждого файла.
cuonglm
Ну, вы можете сделатьfor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
Федорки