Procurando uma maneira de mover linhas pares para o começo de linhas ímpares

1

Estou tentando descobrir como mover todas as linhas pares para o início de todas as linhas ímpares da seguinte forma:

antes:

AAA
BBB
CCC
DDD

depois:

BBBAAA
DDDCCC

Algo que eu possa rodar em vários arquivos de uma só vez seria ótimo, já que combinar todos os arquivos usando o cat resulta em um arquivo que é muito grande para se lidar. Algo semelhante ao seguinte comando para fazer troca de texto para que eu possa adicioná-lo a um arquivo bash:

  find /directory/. -type f -exec sed -i 's/oldtext/newtext/g' {} \;

Eu pesquisei, mas não encontrei algo adequado.

Para facilitar as coisas, posso adicionar 'string1' ao início de todas as linhas ímpares e 'string2' ao início de todas as linhas pares da seguinte forma:

  before:
  string1AAA
  string2BBB
  string1CCC
  string2DDD

  after:
  string2BBBstring1AAA
  string2DDDstring1CCC 

Muito obrigado.

    
por speld_rwong 04.05.2017 / 03:44

5 respostas

2

Esqueça a ideia com o prefixo. O script que você está procurando é

sed 'N;s/\(.*\)\n\(.*\)//'

Ou seja, leia a próxima linha com N , altere a ordem e remova a nova linha.

E você pode combinar isso com o find como você escreveu. Experimente sem a opção -i primeiro para testar se é isso que você quer.

    
por 04.05.2017 / 05:46
1
Solução

gawk :

for f in /directory/*; do gawk -i inplace '{getline nl; print nl$0}' "$f"; done

for f in /directory/* - para cada arquivo no caminho especificado

gawk -i inplace - ativar no lugar edição de arquivos

getline nl - leia o próximo registro da entrada do awk na variável nl (próxima linha)

print nl$0 - imprime o atual e o próximo registro trocado

    
por 04.05.2017 / 07:51
1

Com o GNU sed :

sed '1~2 { h; d; }; G; s/\n//'

com awk :

awk '{ if(NR%2) save = $0; else print $0 save }'

com perl :

perl -pe '$_ = <> . $_; s/\n//'
    
por 04.05.2017 / 11:08
0

Para concluir a resposta da RomanPrekhrest , se você tiver uma versão antiga do gawk como eu que não é compatível edição inplace, ou tenha a instrução getline :

find /path/to/directory/ -exec awk 'NR%2!=0{line=$0; next}{print line $0}END{if(NR%2!=0) print line}' {} > /tmp/mytmpfile.txt \; -exec mv /tmp/mytmpfile.txt {} \;

Também adicionou algo para manipular arquivos com um número ímpar de linhas.

    
por 04.05.2017 / 11:58
0
eval "'echo 'NL=qsq' | tr 'qs' '72''"; # newline
set -- 
while IFS= read -r l; do
   case $# in
      0 ) set -- "$l" ;;
      * ) printf '%s%s\n' "$l" "$1"; set -- ;;
   esac
done < input.data
printf '%s' ${1+"$1$NL"} # to take care of dangling line

awk '{ if ( NR % 2 ) ORS = $0 RS; else print }' input.data

perl -lpe '$_ = (<>.$_) =~ s/\n//r' input.data

sed -ne '
   ${p;d;}
   h;n;G;s/\n//p
' input.data

Resultado

BBBAAA
DDDCCC
    
por 04.05.2017 / 12:33