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

17

Foi-me dito que era possível, mas sem um único exemplo de trabalho, que sed pode ler de uma variável de string sem necessidade de um arquivo de entrada. Eu ainda tenho que fazê-lo funcionar. Para segurança geral, estou escrevendo a variável $PATH para outra variável, já que eu bagunço com isso, porque não preciso que outros problemas surjam até saber 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 algumas outras que 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 que eu não precisei apenas para usar o sed. Para este exemplo em particular, se ~$x=$PATH ~$sed -i 's/:/ /g' $x realmente 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 então atribuir a uma variável e usar em futuros comandos, como ls $x

    
por j0h 10.03.2015 / 22:21

2 respostas

14

Pode ser:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
    
por bolichep 10.03.2015 / 22:38
29

Isso não tem nada a ver com sed , como tal, aplica-se a qualquer programa que lê entrada padrão. Enfim, o que você estava procurando é

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

Não há razão 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 de "string aqui" e é específica de bash, ksh e zsh. Ele serve para passar o valor de uma variável como entrada para um programa que lê a entrada padrão.

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

Note que você também poderia ter feito

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

Finalmente, você realmente não precisa de sed para isso. Você pode fazer tudo no bash diretamente:

echo "${PATH//:/ }"

O acima é um constructo de substituição bash. Dada uma variável $var , um padrão pat e uma substituição ( rep ), para substituir todas as ocorrências de pat por rep , você faria

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

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

echo "${var/pat/rep}"
    
por terdon 10.03.2015 / 23:34

Tags