awk
Esses métodos se repetem para cada par de linhas (1 e 2; 3 e 4; etc), trabalhando para quantos caracteres #
, como na primeira linha de cada par, e assumindo que as duas linhas de cada linha par são do mesmo comprimento.
Compatível com o GNU awk (Linux) e o BSD awk (Mac).
Uso de substrings:
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
O mesmo código, reformatado para telas mais estreitas:
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
Salve uma cópia da primeira linha. -
gsub(/#/,"",$0) ; print $0
Exclua todos os#
da primeira linha (não da cópia) e imprima a primeira linha modificada. -
getline
Vai para a próxima linha. -
for (n=1;n<=length(a);n++)
Passe por cada caractere da cópia de primeira linha.-
if ( substr(a,n,1) != "#" )
Se esta subcadeia de caractere único não for#
,…-
printf "%s",substr($0,n,1)
… imprima o caractere da posição correspondente na segunda linha.
-
-
-
printf "%s",RS
Encerra a segunda linha com um caractere de nova linha.
Usando matrizes:
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
Reformatado para telas mais estreitas:
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=""
Inicializa duas strings em branco. Estas serão versões modificadas das duas linhas de entrada. Esta etapa é necessária se houver mais de duas linhas de entrada. -
elements=split($0,a,"")
Converte a primeira linha de entrada em uma matriz, com um caractere por elemento da matriz. Armazene o número de elementos da matriz como a variávelelements
. -
getline
Vai para a próxima linha. -
split($0,b,"")
Converte a segunda linha de entrada em uma matriz, com um caractere por elemento de matriz. -
for (n=1;n<=elements;n++)
Passe por cada elemento da matriz de primeira linha.-
if (a[n]!="#")
Se este elemento de matriz de caractere único não for#
,…-
{ c = c a[n] ; d = d b[n] }
… então, para cada uma das duas linhas, reter o caractere da posiçãon
.
-
-
-
print c ; print d
Imprima as novas versões das duas linhas.
Cuidado: A versão do awk no Mac (BSD) não manipula automaticamente os elementos da matriz em ordem numérica. Isso inicialmente me deu resultados surpreendentes.
The order in which a ‘for (indx in array)’ loop traverses an array is undefined in POSIX awk and varies among implementations. gawk lets you control the order by assigning special predefined values to PROCINFO["sorted_in"].
Os elementos ainda são numerados 1,2,3,...
no momento da criação com split
, como no GNU awk, mas o BSD awk não os vê necessariamente nessa ordem ao usar for (n in array)
. Assim, você vai ter rabiscos sem sentido.
Para contornar isso, você pode armazenar o tamanho de um array (número de elementos) ao criar o array - por exemplo, elements=split($0,a,"")
- e percorrer os elementos usando for (n=1;n<=elements;n++)
, como fiz aqui.
Exemplo de entrada ( file.txt
):
abcdb#lae#blabl#a
abc~bola~xblabl~a
#alpha#beta#gamma#delta#epsilon#
abcdefghijklmnopqrstuvwxyzabcdef
Exemplo de saída:
abcdblaeblabla
abc~bla~blabla
alphabetagammadeltaepsilon
bcdefhijkmnopqstuvwyzabcde