Excluyendo comillas simples y dobles en una cadena utilizando bash / Linux estándar comandos sólo

StackOverflow https://stackoverflow.com/questions/758031

  •  09-09-2019
  •  | 
  •  

Pregunta

Estoy buscando algo que va a traducir una cadena de la siguiente manera, utilizando sólo bash / Linux estándar comandos:

  1. comillas simples que rodean una cadena deben ser retirados
  2. comillas dobles que rodean una cadena deben ser retirados
  3. cadenas Unquoted deben seguir siendo la misma
  4. Cuerdas con citas de los alrededores inigualables debe seguir siendo el mismo
  5. comillas simples que no rodean la cadena deben permanecer
  6. comillas dobles que no rodean la cadena deben permanecer

Por ejemplo:

  • 'Alimentación' debe convertirse en Alimentaria
  • "alimento" debe convertirse en Alimentaria
  • Los alimentos deben seguir siendo el mismo
  • 'Alimentos" debe seguir siendo el mismo
  • "alimento' debe seguir siendo el mismo
  • 'Fo'od' debe convertirse en Fo'od
  • "Fo'od" debe convertirse en Fo'od
  • Fo'od debe seguir siendo el mismo
  • 'Fo "od' debe convertirse en Fo" od
  • "Fo" od "debe convertirse en Fo" od
  • Fo "od debe seguir siendo el mismo

Gracias!

¿Fue útil?

Solución

Esto debe hacerlo:

sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt

Cuando in.txt es:

"Fo'od'
'Food'
"Food"
"Fo"od'
Food
'Food"
"Food'
'Fo'od'
"Fo'od"
Fo'od
'Fo"od'
"Fo"od"
Fo"od

Y expected.txt es:

"Fo'od'
Food
Food
"Fo"od'
Food
'Food"
"Food'
Fo'od
Fo'od
Fo'od
Fo"od
Fo"od
Fo"od

Puede comprobar que coinciden con:

diff -s <(sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt) expected.txt

Otros consejos

Se puede usar tr:

echo "$string" | tr -d 'chars to delete' 

... también funciona, sin embargo 'tr' es conocido por ser problemático en distribuciones RedHat (alrededor de 9-ish) mucho mayores. tr es una abreviatura de 'traducir', comúnmente utilizado en tuberías para transformar de entrada. La opción -d simplemente significa 'borrar'.

La mayoría de las versiones modernas también contienen macros predefinidas para transformar superior a la inferior, inferior a superior, matar a los espacios en blanco, etc. Por lo tanto, si usted lo usa, tomar un segundo para empujar a lo demás que sí (ver el resultado de la ayuda / hombre página), viene muy bien.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Explicación: Dado que las cotizaciones ya son entendidos por la cáscara puede pedirle a la cáscara para evaluar un comando que simplemente hace eco de la cadena entre comillas, de la misma manera que lo hace cuando se escribe usted mismo

.

A continuación, se expande para eval echo $VAR eval echo 'FOOD' debido a que las citas son en realidad parte del valor de VAR. Si se va a ejecutar echo 'FOOD' en la cáscara se obtendría FOOD (sin las comillas). Eso es lo que hace eval:. Que toma su entrada y lo ejecuta como un comando shell

  

⚠CODE INYECCIÓN!

     

eval exponer scripts para inyección de código.

     
VAR=';ls -l'

VAR=$(eval echo $VAR)
     

hará que la ejecución de ls -l.

     

códigos mucho más dañina podrían inyectarse aquí.

Es posible que desee utilizar sed ...

echo $mystring | sed -s "s/^\(\(\"\(.*\)\"\)\|\('\(.*\)'\)\)\$/\\3\\5/g"

Sólo usando builtins Bash (es decir, la expansión de parámetro Bash):

IFS=' ' 

food_strings=( "'Food'" '"Food"' Food "'Food\"" "\"Food'" "'Fo'od'" "\"Fo'od\"" "Fo'od" "'Fo\"od'" '"Fo"od"' 'Fo"od'  )  

for food in ${food_strings[@]}; do 

   [[ "${food#\'}" != "$food" ]] && [[ "${food%\'}" != "$food" ]] && { food="${food#\'}"; food="${food%\'}"; } 

   [[ "${food#\"}" != "$food" ]] && [[ "${food%\"}" != "$food" ]] && { food="${food#\"}"; food="${food%\"}"; } 

   echo "$food"

done 

En todavía otro ejemplo de Bash expansión de parámetro, véase:

http://codesnippets.joyent.com/posts/show/1816

tropecé con esto también. Durante los tres primeros casos de prueba, eval echo $string funciona bien. Para conseguir que funcione para todos los casos solicitados y algunos otros, se me ocurrió esto (probado con bash y dash):

#!/bin/sh

stripquotes() {
    local firstchar="`substr "$1" 0 1`"
    local len=${#1}
    local ilast=$((${#1} - 1))
    local lastchar="`substr "$1" $(($len - 1))`"
    if [ "$firstchar" = '"' ] || [ "$firstchar" = "'" ] && [ $firstchar = $lastchar ]; then
        echo "`substr "$1" 1 $(($len - 2))`"
    else
        echo "$1"
    fi
}

# $1 = String.
# $2 = Start index.
# $3 = Length (optional). If unspecified or an empty string, the length of the
#      rest of the string is used.
substr() {
    local "len=$3"
    [ "$len" = '' ] && len=${#1}
    if ! (echo ${1:$2:$len}) 2>/dev/null; then
        echo "$1" | awk "{ print(substr(\$0, $(($2 + 1)), $len)) }"
    fi
}

var="'Food'"
stripquotes "$var"

var='"Food"'
stripquotes "$var"

var=Food
stripquotes "$var"

var=\'Food\"
stripquotes "$var"

var=\"Food\'
stripquotes "$var"

var="'Fo'od'"
stripquotes "$var"

var="\"Fo'od\""
stripquotes "$var"

var="Fo'od"
stripquotes "$var"

var="'Fo\"od'"
stripquotes "$var"

var="\"Fo\"od\""
stripquotes "$var"

var="Fo\"od"
stripquotes "$var"

# A string with whitespace should work too.
var="'F\"o 'o o o' o\"d'"
stripquotes "$var"

# Strings that start and end with the same character that isn't a quote or
# doublequote should stay the same.
var="TEST"
stripquotes "$var"

# An empty string should not cause errors.
var=
stripquotes "$var"

# Strings of length 2 that begin and end with a quote or doublequote should not
# cause errors.
var="''"
stripquotes "$var"
var='""'
stripquotes "$var"
python -c "import sys;a=sys.stdin.read();a=a.strip();print (a[1:-1] if a[0]==a[-1] and a[0] in \"'\\\"\" else a)"

no maneja casos extremos muy bien (como una cadena vacía), pero servirá como punto de partida. Funciona mediante la creación de bandas el carácter frontal y posterior si son los mismos y si son "o "

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top