Em 'sed', como posso colocar um “&” entre os caracteres em uma string?

11

Pode sed fazer algo como:

12345

torne-se:

1&2&3&4&5

?

    
por GAD3R 24.08.2017 / 20:46

6 respostas

25

Com o GNU sed :

sed 's/./\&&/2g'

( s ubstitute a cada ( g ) caractere ( . ) com o mesmo ( & ) precedido por & ( \& ) mas apenas a partir da segunda ocorrência ( 2 )).

Portável:

sed 's/./\&&/g;s/&//'

(substitua todas as ocorrências, mas remova o primeiro & que não queremos).

Com algumas implementações awk (não POSIX, pois o comportamento não é especificado para um FS vazio):

awk -F '' -v OFS="&" '{$1=$1;print}'

(com gawk e algumas outras implementações awk , um separador de campo vazio divide os registros em seus constituintes de caracteres . separador de campo de saída ( OFS ) é definido como & . Atribuímos um valor a $1 (próprio) para forçar o registro a ser gerado novamente com o novo separador de campo antes de imprimi-lo, NF=NF também funciona e é um pouco mais eficiente em muitas implementações do awk, mas o comportamento quando você faz isso não é especificado pelo POSIX).

perl :

perl -F -lape '$_=join"&",@F' 

( -pe executa o código para cada linha e imprime o resultado ( $_ ); -l retira e adiciona novamente os finais de linha automaticamente; -a preenche @F com entrada dividida no conjunto delimitador em -F , que aqui é uma string vazia. O resultado é dividir todos os caracteres em @F , depois juntá-los com '&', e imprima a linha.)

Alternativamente:

perl -pe 's/(?<=.)./&$&/g' 

(substitua todos os caracteres desde que sejam precedidos por outro caractere (operador regexp de look-behind (? < = ...))

Usando zsh operadores de shell:

in=12345
out=${(j:&:)${(s::)in}}

(novamente, divida em um separador de campo vazio usando o sinalizador de expansão do parâmetro s:: e junte-se a & )

Ou:

out=${in///&} out=${out#?}

(substitua todas as ocorrências de nada (assim antes de cada caractere) com & usando o operador ${var//pattern/replacement} ksh (embora em ksh um padrão vazio signifique outra coisa, e ainda outra coisa, não tenho certeza do que em bash ) e remova o primeiro com o operador de remoção POSIX ${var#pattern} ).

Usando ksh93 operadores de shell:

in=12345
out=${in//~(P:.(?=.))/
out=${in//?/&
shopt -s extglob
in=12345
out=${in//@()/&}; out=${out#?}
}; out=${out#?}
&}

( ~(P:perl-like-RE) sendo um operador ksh93 glob para usar expressões regulares semelhantes a perl (diferente de perl ou PCRE), (?=.) sendo o operador look-ahead: substitua um caractere desde que seja seguido por outro caractere consigo mesmo ( & ) e ? )

Ou:

sed 's/./\&&/2g'

(substitua todos os caracteres ( & ) por bash e por si ( zsh ), e removemos o superfluço)

Usando @() operadores de shell:

sed 's/./\&&/g;s/&//'

(o mesmo que extglob , exceto que você precisa de bash lá (um operador de ksh glob para o qual você precisa de %code% em %code% )).

    
por 24.08.2017 / 20:56
15

Utilitários Unix:

fold -w1|paste -sd\& -

Explicado:

"fold -w1" - envolverá cada caractere de entrada em sua própria linha

fold - wrap each input line to fit in specified width

-w, --width=WIDTH use WIDTH columns instead of 80

%echo 12345|fold -w1
1
2
3
4
5

"paste -sd\& -" - mesclará as linhas de entrada juntas, usando & como separador

paste - merge lines of files

-s, --serial paste one file at a time instead of in parallel

-d, --delimiters=LIST reuse characters from LIST instead of TABs

%fold -w1|paste -sd\& -
1&2&3&4&5

(Observe que, se a entrada contiver várias linhas, elas serão associadas a & )

    
por 24.08.2017 / 21:02
11

Use sed

sed 's/./&\&/g;s/.$//'
    
por 24.08.2017 / 20:50
9
sed 's/\B/\&/g'

\B - Matches everywhere but on a word boundary; that is it matches if the character to the left and the character to the right are either both “word” characters or both “non-word” characters.

Informações: GNU sed manual, extensões de expressões regulares .

Teste:

sed 's/\B/\&/g' <<< '12345'
1&2&3&4&5
    
por 25.08.2017 / 01:14
4

Isso será um pouco mais lento do que algumas das outras respostas, mas está bem claro:

echo 12345 | perl -lnE 'say join "&", split //'
    
por 24.08.2017 / 21:51
4

Aqui está outro jeito. A primeira parte da expressão sed captura todos os caracteres e substitui-os pelo caractere e um e comercial. A segunda parte remove oe comercial do final da linha.

echo 12345 | sed -r 's/(.)/\&/g;s/\&$//g'
1&2&3&4&5

Funciona também em caracteres multibyte.

    
por 25.08.2017 / 10:06