Dodawanie kolumny wartości w pliku rozdzielanym tabulatorami

17

Jak mogę dodać kolumnę wartości w pliku, który ma określoną liczbę wierszy. Mam plik wejściowy taki jak ten:

Plik wejściowy:

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

Plik wyjściowy:

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

W tym przypadku chcę dodać kolumnę wartości, aż do liczby wierszy w pliku. Wartość pozostaje spójna, na przykład „plik1”.

Powodem jest to, że mam 100 takich plików. Nie chcę otwierać każdego pliku i wklejać kolumny. Istnieje również sposób na zautomatyzowanie tego, przechodząc do katalogu i dodając kolumnę wartości. Wartość pochodzi z nazwy pliku, którą należy dodać w każdym wierszu pliku w ostatniej / pierwszej kolumnie.

Ron
źródło

Odpowiedzi:

22

Możesz użyć pętli jednowierszowej w następujący sposób:

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

W przypadku każdego pliku na liście będzie sedto dopisywać na końcu każdego wiersza tabulator i nazwę pliku.

Wyjaśnienie:

  • Użycie -iflagi z seddo wykonania zamiany w miejscu, nadpisanie pliku
  • Wykonaj podstawienie za pomocą s/PATTERN/REPLACEMENT/. W tym przykładzie WZÓR to $koniec linii, a WYMIANA to \t(= TAB), i $fjest nazwą pliku, od zmiennej pętli. s///Komenda jest w cudzysłów, tak że powłoka może rozwinąć zmiennych.
janos
źródło
Kod działa. Czy możesz wyjaśnić treść w cudzysłowie?
Ron
Tak jak „awk” jest używany podczas pracy z kolumnami, tak samo „sed” jest używany w podobnych sytuacjach. Jestem nowicjuszem w „awk” i „sed”.
Ron
@Ron sedjest najbardziej praktyczny w przypadku zastępowania wzorów i zapisywania w miejscu. Dla twojego wymogu zapisania pliku była to stosunkowo wygodna opcja. Jeśli nie musisz zapisywać tego samego pliku, który przetwarzasz, awkzazwyczaj łatwiej jest pracować.
janos
Osobiście awkzbyt często mnie denerwują separatory pól wejściowych / wyjściowych, dlatego staram się unikać używania go, gdy tylko jest to możliwe, czyniąc je sedbardziej atrakcyjnym.
user5359531
11

Chodźcie, dlaczego polecacie te potężne narzędzia, kiedy istnieje pasterozkaz!

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

Przy odrobinie podstępu możesz użyć pastedo celu PO. Jednak nie zastąpi plików w miejscu:

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

Spowoduje to wklejenie odpowiedniej nazwy pliku jako ostatniej kolumny każdego pliku do nowego pliku filename.new

czatować
źródło
Dzięki! pastejest z pewnością ukrytym klejnotem.
neu242,
10

Możesz użyć awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...
Cuonglm
źródło
Ponieważ każdy plik ma inną nazwę, muszę to zrobić 100 razy. Czy jest jakiś sposób, aby to zrobić raz?
Ron
Nie, FILENAMEjest zmienną w awk, rozwija się do bieżącej awkprzetwarzanej nazwy pliku . Po prostu zrób to jeden, podaj wszystkie pliki do awk.
cuonglm
ok, ale jak skierować dane wyjściowe do nowego pliku każdego pliku? czy awk przechowuje każdy plik podczas przetwarzania?
Ron
Jeśli masz GNU awk 4.1.0lub później, możesz użyć -ido edycji w miejscu. W przeciwnym razie powinieneś przekierować awkwyjście do pliku tymczasowego, a następnie użyć grepdo wyodrębnienia wiersza z każdego pliku.
cuonglm
Cóż, możesz zrobićfor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
fedorqui