awk
Metody te powtarzają się dla każdej pary linii (1 i 2; 3 i 4; itd.), Pracując dla tylu #
znaków, ile jest w pierwszym wierszu każdej pary i zakładając, że dwie linie każdej pary mają tę samą długość.
Kompatybilny z GNU awk (Linux) i BSD awk (Mac).
Za pomocą podciągów:
awk '{ a=$0 ; gsub(/#/,"",$0) ; print $0 ; getline ; for (n=1;n<=length(a);n++) if ( substr(a,n,1) != "#" ) printf "%s",substr($0,n,1) ; printf "%s",RS }' file.txt
Ten sam kod, sformatowany dla węższych ekranów:
awk '{
a=$0 ;
gsub(/#/,"",$0) ;
print $0 ;
getline ;
for (n=1;n<=length(a);n++)
if ( substr(a,n,1) != "#" )
printf "%s",substr($0,n,1) ;
printf "%s",RS
}' file.txt
a=$0
Zapisz kopię pierwszego wiersza.
gsub(/#/,"",$0) ; print $0
Usuń wszystko #
z pierwszego wiersza (nie z kopii), a następnie wydrukuj zmodyfikowany pierwszy wiersz.
getline
Przejdź do następnej linii.
for (n=1;n<=length(a);n++)
Przechodź przez każdy znak kopii pierwszego wiersza.
if ( substr(a,n,1) != "#" )
Jeśli ten jednoznakowy podciąg nie jest #
…
printf "%s",substr($0,n,1)
… Następnie wydrukuj znak z odpowiedniej pozycji w drugim wierszu.
printf "%s",RS
Zakończ drugą linię znakiem nowej linii.
Korzystanie z tablic:
awk '{ c=d="" ; elements=split($0,a,"") ; getline ; split($0,b,"") ; for (n=1;n<=elements;n++) if (a[n]!="#") { c = c a[n] ; d = d b[n] } ; print c ; print d }' file.txt
Przeformatowany dla węższych ekranów:
awk '{
c=d="" ;
elements=split($0,a,"") ;
getline ;
split($0,b,"") ;
for (n=1;n<=elements;n++)
if (a[n]!="#")
{ c = c a[n] ; d = d b[n] } ;
print c ;
print d
}' file.txt
c=d=""
Zainicjuj dwa puste ciągi. Będą to zmodyfikowane wersje dwóch linii wejściowych. Ten krok jest konieczny, jeśli są więcej niż dwa wiersze wprowadzania.
elements=split($0,a,"")
Przekształć pierwszy wiersz danych wejściowych w tablicę, z jednym znakiem na element tablicy. Przechowuj liczbę elementów tablicy jako zmienną elements
.
getline
Przejdź do następnej linii.
split($0,b,"")
Przekształć drugi wiersz danych wejściowych w tablicę, z jednym znakiem na element tablicy.
for (n=1;n<=elements;n++)
Przejdź przez każdy element tablicy pierwszego wiersza.
if (a[n]!="#")
Jeśli ten element tablicy jednoznakowej nie jest #
…
{ c = c a[n] ; d = d b[n] }
… Następnie, dla każdej z dwóch linii, zachowaj znak z pozycji n
.
print c ; print d
Wydrukuj nowe wersje dwóch linii.
Uwaga: Wersja awk dla komputerów Mac (BSD) nie obsługuje automatycznie elementów tablicy w kolejności numerycznej. To początkowo dało mi zaskakujące wyniki.
Kolejność, w jakiej pętla „for (indx in array)” przemierza tablicę, jest niezdefiniowana w POSIX awk i różni się w zależności od implementacji. gawk pozwala kontrolować kolejność, przypisując specjalne predefiniowane wartości do PROCINFO ["sorted_in"].
- Podręcznik użytkownika GNU Awk
Elementy są nadal ponumerowane 1,2,3,...
w momencie tworzenia split
, podobnie jak w GNU awk, ale awk BSD niekoniecznie widzi je w tej kolejności podczas używania for (n in array)
. W ten sposób dostaniesz bełkot.
Aby obejść ten problem, możesz zapisać długość tablicy (liczbę elementów) podczas tworzenia tablicy - np. elements=split($0,a,"")
- a następnie iterować elementy za pomocą for (n=1;n<=elements;n++)
, tak jak to zrobiłem tutaj.
Przykładowe wejście ( file.txt
):
abcdb#lae#blabl#a
abc~bola~xblabl~a
#alpha#beta#gamma#delta#epsilon#
abcdefghijklmnopqrstuvwxyzabcdef
Przykładowe dane wyjściowe:
abcdblaeblabla
abc~bla~blabla
alphabetagammadeltaepsilon
bcdefhijkmnopqstuvwyzabcde