Jak usunąć ostatnią kolumnę pliku w Linuksie

Chcę usunąć ostatnią kolumnę z pliku txt, a nie wiem jaki jest numer kolumny jest. Jak mogłem to zrobić?

Przykład:

Dane wejściowe:

1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222 

I chcę, aby mój wynik był :

1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Komentarze

  • Można to zrobić na wiele sposobów… proszę dodać przykład i Twoje oczekiwane wyjście z tego ..
  • @heemayl ok Tak zrobiłem
  • Dziękuję .. czy kolumny są rozdzielone tabulatorami czy spacjami?
  • @heemayl spacja to separator
  • cut brzmi jak narzędzie do pracy.

Odpowiedź

Z awk:

awk "NF{NF-=1};1" <in >out 

lub:

awk "NF{NF--};1" <in >out 

lub:

awk "NF{--NF};1" <in >out 

Chociaż to wygląda jak voodoo, działa. Każde z tych poleceń awk składa się z trzech części.

Pierwsza to NF, co jest warunkiem wstępnym dla drugiej części. NF to zmienna zawierająca liczbę pól w linii. W AWK rzeczy są prawdziwe, jeśli „nie są 0 lub pustym ciągiem "". Stąd druga część (gdzie NF jest zmniejszane) ma miejsce tylko wtedy, gdy NF nie jest równe 0

Druga część (albo NF-=1 NF-- lub --NF) to po prostu odjęcie jednego ze zmiennej NF. Zapobiega to wydrukowaniu ostatniego pola, ponieważ kiedy zmienisz pole (w tym przypadku usuniesz ostatnie pole), awk skonstruujesz ponownie $0, połącz wszystkie pola domyślnie rozdzielone spacjami . $0 nie „nie zawierało już ostatniego pola.

Ostatnia część to 1. To nie jest magiczne, jest po prostu używane jako wyrażenie oznaczające true. Jeśli wyrażenie awk daje wartość „prawda” bez powiązanego działania, awk działaniem domyślnym jest print $0 .

Komentarze

  • @JJoao: Ach, dzięki, zapomniałem o --. Uwaga, obecnie potrzebujesz ;1 dla zgodności z POSIX.
  • Moim początkowym instynktem byłoby użycie pętli for, ale jest to znacznie bardziej zwięzłe i sprytne.
  • ' warto zauważyć, że jeśli ' używasz innego niż domyślny separatora, ' Będziemy musieli wprowadzić pewne zmiany. Zakładając, że , jest twoim ogranicznikiem: awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
  • Efektem dekrementacji NF jest niezdefiniowane zachowanie według POSIX – otrzymasz różne wyniki w zależności od tego, który awk ' uruchamiasz. Niektóre awks usuwają ostatnie pole tak, jak chcesz, niektóre nie zrobią nic, a inne mogą zgłosić błąd składni lub cokolwiek innego.

Odpowiedź

Używanie grep z PCRE:

$ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Używanie GNU sed:

$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334 

Komentarze

  • @ramin Sure. . czy mógłbyś zadać to jako nowe pytanie (tak działa ta strona) 🙂
  • @ramin Czy daje jakieś ograniczenie czasowe lub jakieś ostrzeżenie?
  • mówi, że to nie jest standardowe pytanie!
  • @ramin Ok .. pozwól mi skontaktować się z administratorem, może on może ci w tym pomóc .. przy okazji, czy sprawdziłeś jakąś starą kontrolę jakości dotyczącą twojego pytania? istnieje możliwość, że pytanie zostało już zadane i udzielono na nie odpowiedzi.
  • Nie ' nie zadawaj podstawowych pytań, takich jak " jak zmienić nazwę pliku w systemie Linux ". Korzystaj z Google.

Odpowiedz

Za pomocą Perla:

perl -lane "$,=" ";pop(@F);print(@F)" in 

Używając rev + cut:

rev in | cut -d " " -f 2- | rev 

Odpowiedź

Używanie GNU sed:

sed -r "s/\s+\S+$//" input.txt 

Mówiąc bardziej ogólnie, ten działa z sedami BSD w OSX, a także z sedami GNU:

sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt 

Odpowiedź

Jeśli separatorem jest zawsze pojedynczy znak (więc dwa lub więcej kolejnych separatorów oznacza puste pola), możesz head tylko pierwszy wiersz z pliku wejściowego, policzyć ograniczniki ( n ograniczniki oznacza, że liczba pól wynosi n+1), a następnie użyj cut, aby wydrukować z 1 st pole aż do n pola (przedostatniego), np. z danymi wejściowymi rozdzielanymi znakami tabulacji:

n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile 

lub np.z plikiem csv :

n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile 

Później przeprowadzę testy porównawcze, jeśli będę miał czas, ale przy dużym wkładzie myślę, że to rozwiązanie powinno być szybsze niż inne rozwiązania, które używają wyrażenia regularnego, ponieważ ten wykonuje minimalne przetwarzanie w pierwszej linii, aby uzyskać liczbę pól, a następnie używa cut, który jest zoptymalizowany do tego zadania. / p>

Odpowiedź

Przenośnie możesz użyć jednego z poniższych:

sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file 

Odpowiedz

Używanie vim:

Otwórz plik w vimie

vim <filename> 

Idź do pierwszego wiersza, na wypadek gdyby kursor został umieszczony w innym miejscu.

gg 

Utwórz makro o nazwie „q” qq, który przechodzi na koniec bieżącego wiersza $, a następnie wraca do ostatniej spacji F (duże F, po którym następuje dosłowny SPACJA), a następnie usuń od bieżącej pozycji do końca wiersza D przejdź do następnej linii j i zatrzymaj nagrywanie makra za pomocą q.

qq$F Djq 

Teraz możemy powtórzyć nasze makro z @q dla każdego wiersza.
Możemy również nacisnąć @@ aby powtórzyć ostatnie makro lub nawet łatwiej:

99@q 

powtórzyć makro 99 razy.
Uwaga: liczba nie może dokładnie odpowiadać wierszom.

Odpowiedź

Dla osób, które mają podobny problem, ale z różnymi separatorami pól, awk zachowa poprawnie separator pól:

$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *