Use sed en una variable de cadena en lugar de un archivo

30

Me dijeron que era posible, pero sin un solo ejemplo de trabajo, que sedpuede leer desde una variable de cadena sin necesidad de un archivo de entrada. Todavía tengo que hacerlo funcionar. Por seguridad general, estoy escribiendo la $PATHvariable en otra variable, ya que me meto con esto, porque no necesito que surjan otros problemas hasta que sepa exactamente cómo hacerlo.

Considera lo siguiente:

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

esto falla con: No existe tal archivo o directorio.

Aquí hay algunos otros que he probado:

~$ 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

¿Esto puede funcionar? Preferiría no tener que escribir archivos que no necesito solo para poder usar sed. Para este ejemplo en particular, si ~$x=$PATH ~$sed -i 's/:/ /g' $xrealmente funcionara de la manera que esperaba, obtendría:

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

que luego podría asignar a una variable y usar en futuros comandos, como ls $x

j0h
fuente
1
x=$(echo "$x" | sed 's/:/ /g')?
heemayl

Respuestas:

16

Tal vez:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
bolichep
fuente
@jOh --- observe que sedaquí no funciona en la "variable de cadena" (?), sino en la entrada estándar --- que es como debería ser.
Rmano
Creo que haré una solicitud de función a los desarrolladores de sed
j0h
44
@ j0h esto no tiene nada que ver sed, se trata de cómo el shell redirige la entrada. sedtrata con flujos de entrada y los lee a través de su entrada estándar. Si son archivos o no es irrelevante. Puede aceptar cualquier cosa, siempre que provenga de una entrada estándar.
terdon
38

Esto no tiene nada que ver sedcomo tal, se aplica a cualquier programa que lea entradas estándar. De todos modos, lo que estabas buscando es

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

No hay razón para guardar en otra variable, nada de lo que haga de esta manera afectará el valor almacenado en la variable. Necesita el operador de asignación ( =) para eso. La sintaxis utilizada anteriormente se denomina "cadena aquí" y es específica de bash, ksh y zsh. Sirve para pasar el valor de una variable como entrada a un programa que lee desde la entrada estándar.

He escrito una respuesta en U&L que enumera todos los diversos operadores de shell como este. Es posible que desee echar un vistazo.

Tenga en cuenta que también podría haber hecho

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

Finalmente, realmente no necesitas sednada para esto. Puedes hacer todo en bash directamente:

echo "${PATH//:/ }"

Lo anterior es una construcción de reemplazo de bash. Dada una variable $var, un patrón paty un reemplazo ( rep), para reemplazar todas las apariciones de patla rep, que haría

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

Lo mismo con una barra inclinada solo reemplaza la primera aparición:

echo "${var/pat/rep}"
terdon
fuente
2
Gracias por 'bash replace construct'. Pude usar: "$ {1 / from / to}" en una función Bash para alterar el primer argumento en los parámetros posteriores.
AAAfarmclub