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.

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.

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


Dzięki! pastejest z pewnością ukrytym klejnotem.
— neu242,

10

Możesz użyć awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.