Como substituo todas as ocorrências de um símbolo, exceto o último usando sed?

2

Por exemplo, eu tenho uma linha como esta:

44567743346_567864_56788_5677_3

Eu quero alterar todo o _ para : , exceto que o último seria alterado para \ . A saída esperada é:

44567743346:567864:56788:5677
    
por Lucas Lau 15.08.2015 / 09:06

4 respostas

4

$ echo '44567743346_567864_56788_5677_3' | sed -r 's|_|:|g; s|:([^:]*)$|\|'
44567743346:567864:56788:5677

Isso usa dois comandos de substituição de sed. O primeiro, s|_|:|g altera todos os sublinhados para dois pontos. O segundo, s|:([^:]*)$|\| , encontra os últimos dois pontos e os altera para uma barra invertida.

Modificando cada quarta linha de um arquivo dessa maneira

sed -r '1~4{s|_|:|g; s|:([^:]*)$|\|;}' file

Para modificar o arquivo no local:

sed -i -r '1~4{s|_|:|g; s|:([^:]*)$|\|;}' file
    
por John1024 15.08.2015 / 09:21
2

Um Simple One usando sed

echo "44567743346_567864_56788_5677_3" | rev | sed "s/_/:/2g" | sed 's/_/\/' | rev

Agora vamos ver como funciona: -

1) rev inverte a string,

torna-se 3_7765_88765_468765_64334776544

2) sed "s/_/:/2g substitui toda a ocorrência de _ a : , exceto a primeira ocorrência na string invertida,

torna-se, 3_7765:88765:468765:64334776544

3) Próximo sed , ou seja, sed 's/_/\/' substitui apenas a primeira ocorrência de _ a \ .

Torna-se, 365:88765:468765:64334776544

4) rev reverte esta string processada

Agora, a string final é: -

44567743346:567864:56788:5677

Agora, está concluído !

Nota : não dá muita eficiência. É aqui apenas porque o seu simples

    
por Devesh Saini 09.06.2017 / 11:11
1

Se você sabe a contagem da última ocorrência de _ , por exemplo no seu exemplo, o último _ é o quarto _ na linha, você pode fazer:

sed 's/_/\/4; s/_/:/g' file.txt

Aqui primeiro convertemos a 4ª (última) ocorrência de _ para \ , depois as ocorrências restantes de _ são convertidas em : .

Por exemplo:

$ echo '44567743346_567864_56788_5677_3' | sed 's/_/\/4; s/_/:/g'
44567743346:567864:56788:5677

Por outro lado, se você não souber a posição da última ocorrência de _ , poderá compará-la à última ocorrência de _ , substituí-la por \ e substituir o restante por : :

sed -r 's/^(.*)_/\/; s/_/:/g' file.txt

Por exemplo:

$ echo '44567743346_567864_56788_5677_3' | sed -r 's/^(.*)_/\/; s/_/:/g'
44567743346:567864:56788:5677
    
por heemayl 15.08.2015 / 18:33
0

Por que sed é mais simples usando awk ?

awk -F_ '{printf "%s",; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\%s\n",$NF}' your_input_file

E como você disse em um comentário? você precisa apenas de cada quarta linha

awk -F_ '(NR % 4) == 1 {printf "%s",; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\%s\n",$NF; next} {print}'  your_input_file

Exemplo

Arquivo de entrada

% cat foo
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1_44567743346_567864_56788_5677_3
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22

Saída de comando para alterar a cada quarta linha

% awk -F_ '(NR % 4) == 1 {printf "%s",; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\%s\n",$NF; next} {print}' foo
1:44567743346:567864:56788:5677
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22
1:44567743346:567864:56788:5677
2_908798_08098_878_24332_24_24244_22
3_44567743346_567864_56788_5677_3
4_908798_08098_878_24332_24_24244_22

Saída de comando para alterar cada linha

% awk -F_ '{printf "%s",; for(i=2;i<NF;i++){printf ":%s",$i}; printf "\%s\n",$NF}' foo                               
1:44567743346:567864:56788:5677
2:908798:08098:878:24332:24:24244
3:44567743346:567864:56788:5677
4:908798:08098:878:24332:24:24244
1:44567743346:567864:56788:5677
2:908798:08098:878:24332:24:24244
3:44567743346:567864:56788:5677
4:908798:08098:878:24332:24:24244
1:44567743346:567864:56788:5677
2:908798:08098:878:24332:24:24244
3:44567743346:567864:56788:5677
4:908798:08098:878:24332:24:24244
1:44567743346:567864:56788:5677
2:908798:08098:878:24332:24:24244
3:44567743346:567864:56788:5677
4:908798:08098:878:24332:24:24244
    
por A.B. 15.08.2015 / 09:35