Próbuję zmienić kolejność linii w określonym wzorze. Praca z plikiem zawierającym wiele linii (np. 99 linii). Dla każdych trzech linii chciałbym, aby druga linia była trzecią linią, a trzecią linią drugą.
PRZYKŁAD.
1- Wejście:
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...
2-wyjściowe:
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...
linux
text-processing
command-line
Annick Raymond
źródło
źródło
NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.Oznacza to, że
p
przeszukuj bieżącą linię, pobierzn
ext,h
stary, pobierzn
ext,G
i przytrzymaj linię (dołącz do przestrzeni wzorów) ip
zrewiduj tę 2-liniową przestrzeń wzorów z zamienionymi trzecią i drugą linią.źródło
Kolejne podejście awk :
Wyjście:
(getline L2)>0 && (getline L3)>0
- wyodrębnia 2 kolejne rekordy, jeśli istniejąkażdy drugi i trzeci rekord są przypisane odpowiednio do zmiennych
L2
iL3
zmiennychźródło
line2
itp.Korzystanie
perl
i krótki skrypt:Skrypt przetwarza cały plik, dla każdej linii (zapisanej w
$_
) otrzyma kolejne dwie linie ($l2
i$l3
) i wydrukuje je w żądanej kolejności: linia1, linia3, linia2.źródło
Jednym ze sposobów może być:
Alternatywnie,
Wyniki
źródło
Dlaczego nie zrobić pętli while? W rozszerzonej formie:
W „formacie jednowierszowym”:
Wyjścia:
źródło
Perl
Chodzi o to, że używamy operatora modulo
%
ze$.
zmienną numeru linii , aby dowiedzieć się, który z nich jest co pierwszy, a który co sekundę, a który co 3 linię. Dla każdej trzeciej linii pozostała wartość wynosi 0, natomiast dla każdej pierwszej i drugiej linii będzie mieć odpowiadające jej liczby.Test:
Niewielka poprawa
Podejście polegające na przechowywaniu drugiej linii w zmiennej ma wadę. Co jeśli ostatni wiersz to „drugi”, tzn. Dla tego numeru reszta to 2? Oryginalny kod w mojej i DopeGhoti odpowiedzi nie zostanie wydrukowany,
My dog is orange
jeśli pominiemy ostatni wiersz. Rozwiązaniem tego problemu w obu przypadkach jest użycieEND{}
bloku kodu z rozbrajaniem zmiennej tymczasowej po wydrukowaniu. Innymi słowy:i
W ten sposób kod będzie działał dla dowolnej liczby wierszy w pliku, nie tylko tych podzielnych przez 3.
Dodatkowa poprawka dotycząca problemu wymienionego w komentarzach
W przypadku awk, jeśli ostatni wiersz w pliku daje wynik 1 dla $. % 3, poprzedni kod miał problem z wyświetlaniem pustego znaku nowej linii z powodu bezwarunkowego drukowania
END{print delay}
, ponieważprint
funkcja wymieniona w komentarzach zawsze dołącza znak nowej linii do dowolnej zmiennej, na której działa. W przypadkuperl
wersji ten problem nie występuje, ponieważ funkcja z-ne
flagamiprint
nie dołącza nowego wiersza.Niemniej jednak poprawką w przypadku awk jest uzależnienie, jak wspomniał Dope Ghoti w komentarzach, aby zweryfikować długość zmiennej tymczasowej. Wersja tej samej poprawki dla Perla to:
źródło
awk
)NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.-ne
flagami nie wyświetla nowej linii. Rzeczywiście drukuje, ale jest to ciąg zerowy, bez końca nowej linii. Niemniej jednak do mojej odpowiedzi dodałem wzmiankę o tym problemie i tę samą poprawkę. Dzięki !Wigor
Nie nadaje się do długich plików, ale nadal jest przydatny, jeśli właśnie edytowałeś plik i chciałeś na przykład zmienić kolejność niektórych yamlowych zwrotek.
Najpierw zapisz makro:
A następnie powtórz żądaną liczbę razy:
Lub po prostu np
Wyjaśnienie:
źródło
@q @q @q
można to zrobić w ten sposób3@q
- powtórz trzykrotnie.100@q
- powtórz makro 100 razy.Stosowanie:
./shuffle_lines.awk input.txt
Sprawdź shebang
#!/usr/bin/awk -f
, ponieważawk
lokalizacja może się różnić w twoim systemie.źródło