Pode 'sed' substituir os espaços 5 e 7 em cada linha com um único comando 's /' substituto?

2

Eu posso substituir apenas os espaços 5 e 7 com o comando:

$ echo "1 2 3 4 5 6 7 8" | sed 's/\ /x/5;s/\ /x/6'
1 2 3 4 5x6 7x8

mas talvez sed suporta listas e intervalos de ocorrências de padrão n th para usar apenas um substituto s/ em vez de os dois serem separados por ponto e vírgula?

$ echo "1 2 3 4 5 6 7 8" | sed 's/\ /x/5,7'
sed: -e expression #1, char 9: unknown option to 's'
    
por DonJ 22.03.2018 / 16:47

3 respostas

2

Com shells com csh - como expansão de contraventamento (csh, tcsh, zsh, bash, pdksh, ksh93, yash -o braceexpand , fish ), você poderia fazer:

$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'{7,6,5}
1 2 3 4 5x6x7x8 9 

A expansão da chave expande isso para

sed '-es/ /x/'7 '-es/ /x/'6 '-es/ /x/'5

Estamos fazendo isso de forma que uma substituição não influencie a próxima.

Você pode torná-lo um intervalo com o formulário {x..y} de zsh (agora também suportado por bash, ksh93, yash -o braceexpand )

$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'{7..3}
1 2 3x4x5x6x7x8 9

ou combinações de ambas as formas:

$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'{{7..3},1}
1x2 3x4x5x6x7x8 9

Com zsh , você pode colocá-los em uma matriz:

$ substs=({7..5} 3 1)
$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'$^substs
1x2 3x4 5x6x7x8 9

E tenha zsh ordenando-os na ordem numérica inversa correta:

$ substs=(1 8 6)
$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'${(On)^substs}
1x2 3 4 5 6x7 8x9

Com zsh ou bash , você também pode fazer:

$ substs=({7..5} 3 1)
$ echo 1 2 3 4 5 6 7 8 9 | sed "${substs[@]/#/-es: :x:}"
1x2 3x4 5x6x7x8 9

Com fish (e GNU seq ), você pode fazer coisas como:

$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'(seq 6 -1 3)
1 2 3x4x5x6x7 8 9

Ou:

$ set substs 5 3 1
$ echo 1 2 3 4 5 6 7 8 9 | sed '-es/ /x/'$substs
1x2 3x4 5x6 7 8 9

( fish arrays expandem como em rc ou zsh -o rcexpandparam neste exemplo).

Com perl , você pode fazer algo como:

$ echo 1 2 3 4 5 6 7 8 9 | perl -pe 'BEGIN{$h{$_}=1 for (3,5..8)}
                                     my $n; s/ /$h{++$n} ? "x" : $&/ge'
1 2 3x4 5x6x7x8x9
    
por 23.03.2018 / 07:27
0
$ echo $SHELL
/bin/bash
$ set -- 6 7 # or bash -s 6 7 (set positional parameters)
$ echo "1 2 3 4 5 6 7 8" | sed "s/ /x/$1"
1 2 3 4 5 6x7 8
$ shift # ¹
$ echo "1 2 3 4 5 6 7 8" | sed "s/ /x/$1"
1 2 3 4 5 6 7x8

¹:

$ help shift
shift: shift [n]
Shift positional parameters.

Rename the positional parameters $N+1,$N+2 ... to $1,$2 ... If N is not given, it is assumed to be 1.

Exit Status: Returns success unless N is negative or greater than $#

    
por 22.03.2018 / 22:00
0

Você pode conseguir isso com GNU sed da seguinte forma, considerando que o intervalo que deseja substituir é 5~12 (inclusive) como um exemplo e assumindo que não houve # em seu arquivo em tudo (ou use outro caractere em vez de # que é garantia de que isso não ocorrerá), então você pode fazer:

sed 's/ /#/13g; s/ /x/5g ; s/#/ /g' infile
  • s/ /#/13g , substitui todos os espaços na posição 13 th até o final com #
  • s/ /x/5g , substitui todos os espaços na posição 5 th até o final (que vai até a posição 12 th ) com x .
  • s/#/ /g , reverta todos os espaços.
por 22.03.2018 / 23:57

Tags