Jak mogę usunąć 5. słowo każdego wiersza w pliku?


13

Chcę usunąć 5. słowo każdego wiersza w pliku.

Obecna zawartość pliku:

File is not updated or and will be removed  
System will shut down f within 10 seconds  
Please save your work 55 or copy to other location  
Kindly cooperate with us D  

Oczekiwany wynik:

File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us

Odpowiedzi:


31

Co powiesz na cut:

$ cut -d' ' -f1-4,6- file.txt 
File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
  • -d' ' ustawia separator jako spację

  • -f1-4,6- wybiera od pierwszego do czwartego pola (słowa), pozostawiając 5., a następnie kontynuuje drukowanie od 6. do reszty.


11

Rozwiązanie z cut:

cut -d ' ' -f1-4 -f6- FILE

Wiele -fnie jest obsługiwane w moim cut(GNU) przynajmniej ..
heemayl

Obsługiwane w skrócie BSD, ale bardziej podoba mi się twoja odpowiedź niż moja.
fd0

1
Jeśli jest to GNU cięcie, masz --complementflagę uproszczenia rzeczy: cut --complement -d ' ' -f5. Pamiętaj, aby przekierować wyjście do nowego pliku, a następnie mvna oryginał.
Toby Speight

6

awk: usuwa 5. pole

awk '{for (i=5; i<NF; i++) $i = $(i+1); NF--};1' file

Jeśli chcesz zapisać plik w miejscu: /programming//q/16529716/7552

Możesz po prostu usunąć zawartość 5. pola, ale pozostawia to dwa kolejne separatory pól wyjściowych:

awk '{$5 = ""};1' file

zastrzeżeniem jest to, że zmiana wartości dowolnego pola w awk powoduje efekt uboczny przepisania całego „0 $” z tylko 1 separatorem między każdym polem. należy wziąć pod uwagę, jeśli chcesz zachować jakiekolwiek wyrównanie (chyba że gnu awk ma opcję uniknięcia tego? zwykły awk / nawk ponownie obliczy 0 USD)
Olivier Dulac

W obu przypadkach ponownie sformatujesz linię za pomocą jednego separatora. Jeśli w separatorze są 2 spacje lub spacja + tab, wynikiem jest pojedyncza spacja na miejscu. Mam nadzieję, że jest to OK dla większości tekstu.
NeronLeVelu,

4

Z POSIX sed:

sed -e 's/[^[:alnum:]_][[:alnum:]_][[:alnum:]_]*//4' <file

po co ograniczać klasę do: alnum: _ a nie niczego innego wtedy :blank:lub :space:?
NeronLeVelu,

@NeronLeVelu: To zależy od tego, jak zdefiniujesz, co tworzy słowo.
cuonglm,

@mikeserv; Dobry chwyt! Zaktualizowałem swoją odpowiedź.
cuonglm

Do czego \(służy grupa przechwytywania \)?
mikeserv

@mikeserv: moje błędne pisanie, właśnie wypróbowałem kilka sposobów na zachowanie ogranicznika.
cuonglm

2

glenn zaproponował rozwiązanie równoważne

awk '{$ 5 = ""; print}” plik

Jak zauważył on i inni

  1. usuwa wiodące i końcowe białe spacje z każdej linii,
  2. kompresuje każdy ciąg białych znaków (spacje i / lub tabulatory) w jedną spację, oraz
  3. pozostawia dwie spacje między czwartym a sześcioma słowami.

Hack, aby rozwiązać trzeci problem, to

awk '{$ 5 = ""; print} ' plik | sed 's / / /'

To pozostawi jedno lub więcej dodanych spacji na końcu każdego wiersza, w którym było pięć lub mniej słów. Jeśli potrafisz zidentyfikować słowo, które nigdy nie pojawi się na wejściu,

awk '{5 $ = "jednorożec"; print} ' plik | sed 's / * jednorożec //'

poradzi sobie nawet z tym (ale nadal pozostawia problemy 1 i 2).


2
 sed 's/^\(\([[:blank:]]*[^[:blank:]]\{1,\}\)\{4\}\)[[:blank:]]*[^[:blank:]]*/\1/' YourFile > Output.txt
  • posix sed na podstawie separatora spacji / tabulatorów (meta class [: blank:]])
  • zachowaj następującą spację po 5. słowie, ale usuwając poprzednią

Bardziej wytrzymały (sed bierze najdłuższy możliwy wzorzec i wzorzec z *może pomijać separację lub słowo w pierwszej wersji), ale nieco dłuższą wersję

sed 's/^\([[:blank:]]*\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{4\}\[^[:blank:]]\{1,\}/\1/' YourFile > Output.txt

1
sed 's/[^[:blank:]]*//5'
mikeserv

@ Mikeserv, to pozwoli zachować oba otaczające separatory, sed 's/[[:blank:]*[^[:blank:]]*//5'jest lepiej. Bardzo dobra uwaga. Podejrzewałem, że sed bierze każdy pojedynczy znak jako byt, ale ma największy niezakłócony wzór jako byt
NeronLeVelu

sed 's/[[:blank:]][^[:blank:]]*//4'całkowicie usunie 5. pole.
mikeserv

@mikeserv Zakładając, że na linii nie ma początkowego miejsca (jak w próbce)
NeronLeVelu

W tym przypadku tak, myślę, że masz rację. Zwykle coś takiego byłoby polem zerowym i zachowanie byłoby prawidłowe. W tym przypadku należy zrobić jak @cuonglm zrobił i zapewnić odwołać słowo za każdym razem jak sed 's/[[:blank:]][^[:blank:]][^[:blank:]]*//4', albo w / GNU / BSD / toybox seds: sed -E 's/[[:blank:]][^[:blank:]]+//4'.
mikeserv

1

Perl

perl -ne 'print $_ =~ /^(\w+ +\w+ +\w+ +\w+ +)\w+ (.*)/,"\n"' file


-1

Używając Perla> 5.10 (i z powodzeniem wypisując wszystkie linie: 0)): -

perl -nE '/^((\w+ +){4})\w+ *(.*)/; say $1.$3' file
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.