Bolha a's antes de b com sed

1

Eu tenho um arquivo, que contém apenas a's e b's.

aaaaaaaaaaaaaabbbbbb
abababaaaabbbaabababa
bbbbbaaaaaa
aaabbbabbbaaaabbaba
abababbabbababbbabbab
abababbababaabaaabbababbaba
bababbbababba

Eu gostaria de classificar todos os a's antes de b com sed, assim:

    aaaaaaaaaaaaaabbbbbb
    aaaaaaaaaaaabbbbbbbbb
    aaaaaabbbbb
    aaaaaaaaaabbbbbbbbb
    aaaaaaaabbbbbbbbbbbbb
    ...

Eu tentei escrever este script

for row in $(sed -n 'p' $1)
do
    for k in $(seq $((${#row}-2)))
    do
        for j in $(seq $((${#row}-k-1)))
        do
           if [[  "${row:$j:1}" == a  &&  "${row:$j+1:1}" == b ]]; then
               sed -e  "s/./a/$j+1/p" $row  >> out.txt
           fi
        done
    done
done

Mas não funciona e eu não sei realmente como fazê-lo funcionar. Mas depois de escrever este script, eu percebi que, eu posso fazer isso mais facilmente com os rótulos sed.

Mas o que eu não sei, como faço para definir a condição de teste em sed, que verifica se 'a' está antes de 'b' ou como posso definir o número de loops no sed?

    
por Muffy 11.05.2017 / 20:49

4 respostas

4

Eu criei um arquivo chamado test.txt e executei o seguinte comando:

sed -e ':loop' -e 's/ba/ab/' -e 't loop' test.txt
    
por 11.05.2017 / 21:01
4

Uma maneira um pouco mais eficiente com sed :

sed 'h; s/b//g; x; s/a//g; H; x; s/\n//' file.txt

com perl :

perl -lpe '$_ = y/b//dr . y/a//dr' file.txt

Outra maneira com perl :

perl -lpe '$_ = join "", sort split //' file.txt

(isso funciona porque "a" lt "b" ).

Com o GNU awk :

awk '{ print gensub(/b/, "", "g") gensub(/a/, "", "g") }' file.txt

com bash :

while read -r line; do
    printf '%s%s\n' "$( tr -d b <<<"$line" )"  "$( tr -d a <<<"$line" )"
done <file.txt
    
por 11.05.2017 / 21:02
1
if [[  "${row:$j:1}" == a ...

Se você está indo nessa direção, eu acho que você poderia fazer tudo isso em shell:

while read -r s ; do
    for (( i = 0 ; i < ${#s} ; i++ )) ; do 
        [ "${s:i:1}" = "a" ] && astr+=a || bstr+=b
    done
    echo "$astr$bstr"
done
    
por 11.05.2017 / 23:23
0
perl -pe 's/(b+)(a+)/$2$1/ while /ba/'  data.file

desde que um registro inclua "b" seguido de "a", continuamos a inverter as "ilhas" de abelhas e ayes no registro atual.

perl -F\(b+\) -lne '
   my @A;
   splice @A, (/b/ ? @A : 0), 0, $_  for @F;
   print @A;
' data.file

Inicializamos uma matriz @A para cada registro / linha lida. Os campos esculpidos a partir do registro (armazenados em @F) são examinados e quando contêm um "b" são empurrados para o final da matriz, caso contrário, colocados no inicio. Finalmente, imprimimos o array.

    
por 12.05.2017 / 21:06