Use sed em uma variável de string em vez de em um arquivo

30

Foi-me dito que era possível, mas sem um único exemplo de trabalho, que sedpode ler a partir de uma variável de string sem a necessidade de um arquivo de entrada. Ainda tenho que fazê-lo funcionar. Para segurança geral, estou gravando a $PATHvariável em outra variável, pois mexo com isso, porque não preciso que outros problemas surjam até que eu saiba exatamente como fazer isso.

Considere o seguinte:

~$x=$PATH
~$sed -i 's/:/ /g' $x

isso falha com: Nenhum arquivo ou diretório.

Aqui estão alguns outros que eu tentei:

~$ sed -i 's/:/ /g' | (read x) 
sed: no input files
~$ sed -i 's/:/ /g' | (read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' | $(read x) 
sed: no input files
~$ sed -i 's/:/ /g' | $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' < $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
bash: $(read $x): ambiguous redirect
~$ sed -i 's/:/ /g' < read $x 
bash: read: No such file or directory
~$ sed -i 's/:/ /g' < (read x) 
bash: syntax error near unexpected token `('
~$ sed -i 's/:/ /g' < $((read x)) 
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: syntax error: operand expected (error token is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' < $((read $x)) 
bash: read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: division by 0 (error token is "usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' << $((read $x)) 
> ;^C
~$ sed -i 's/:/ /g' << $(read $x)
> ;^C
~$ sed -i 's/:/ /g' $x
sed: can't read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < $x
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < echo $x
bash: echo: No such file or directory
~$ sed -i 's/:/ /g' |  echo $x
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
sed: no input files

Isso pode funcionar? Eu preferiria não precisar escrever arquivos de que não preciso apenas para poder usar o sed. Para este exemplo em particular, se ~$x=$PATH ~$sed -i 's/:/ /g' $xrealmente funcionasse da maneira que eu esperava, obteria:

/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games

que eu poderia atribuir a uma variável e usar em comandos futuros, como ls $x

j0h
fonte
1
x=$(echo "$x" | sed 's/:/ /g')?
precisa saber é

Respostas:

16

Talvez:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
bolichep
fonte
@jOh --- observe que sedaqui não está funcionando na "variável de string" (?), mas na entrada padrão --- como é que deve ser.
Rmano 10/03/2015
eu acho que eu vou fazer um pedido de recurso para os devs sed
j0h
4
@ j0h isso não tem nada a ver sed, é uma questão de como o shell redireciona a entrada. sedlida com fluxos de entrada e os lê através de sua entrada padrão. Sejam arquivos ou não, é irrelevante. Ele pode aceitar qualquer coisa, desde que seja fornecido com entrada padrão.
terdon
38

Isso não tem nada a ver com sedisso, pois se aplica a qualquer programa que leia a entrada padrão. Enfim, o que você estava procurando é

sed 's/:/ /g' <<<"$PATH"

Não há motivo para salvar em outra variável, nada que você faça dessa maneira afetará o valor armazenado na variável. Você precisa do operador de atribuição ( =) para isso. A sintaxe usada acima é chamada "aqui string" e é específica para bash, ksh e zsh. Serve para passar o valor de uma variável como entrada para um programa que lê da entrada padrão.

Eu escrevi uma resposta no U&L que lista todos os vários operadores de shell como este. Você pode querer dar uma olhada.

Observe que você também poderia ter feito

echo "$PATH" | sed 's/:/ /g' 

Finalmente, você realmente não precisa de sednada para isso. Você pode fazer a coisa toda diretamente no bash:

echo "${PATH//:/ }"

A descrição acima é uma construção de substituição do bash. Dada uma variável $var, um padrão pate uma substituição ( rep), para substituir todas as ocorrências de patwith rep, você faria

echo "${var//pat/rep}"

A mesma coisa com uma única barra substitui apenas a primeira ocorrência:

echo "${var/pat/rep}"
Terdon
fonte
2
Obrigado por 'bash substituição de construção'. Consegui usar: "$ {1 / from / to}" em uma função Bash para alterar o primeiro argumento nos parâmetros subsequentes.
AAAfarmclub