Décapage guillemets simples et doubles dans une chaîne en utilisant bash / Linux standard uniquement les commandes

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

  •  09-09-2019
  •  | 
  •  

Question

Je cherche quelque chose qui se traduira par une chaîne comme suit, en utilisant uniquement bash / commandes Linux standard:

  1. guillemets simples autour d'une chaîne doivent être supprimés
  2. guillemets doubles autour d'une chaîne doivent être supprimés
  3. chaînes non cotées devraient rester les mêmes
  4. Les chaînes avec inégalés guillemets devrait rester la même
  5. guillemets simples qui n'entourent la chaîne doivent rester
  6. guillemets doubles qui n'entourent pas la chaîne doivent rester

Par exemple:

  • 'Food' devrait devenir alimentaire
  • "Food" devrait devenir alimentaire
  • Les aliments doivent rester la même
  • 'Food » devrait rester la même
  • "Food » devrait rester la même
  • 'Fo'od' devrait devenir Fo'od
  • "Fo'od" devrait devenir Fo'od
  • Fo'od devrait rester la même
  • 'Fo "od' devrait devenir Fo" od
  • "Fo" od "devrait devenir Fo" od
  • Fo "od devrait rester la même

Merci!

Était-ce utile?

La solution

Cela devrait le faire:

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

Où in.txt est:

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

Et expected.txt est:

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

Vous pouvez vérifier qu'ils correspondent à:

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

Autres conseils

Vous pouvez utiliser tr:

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

... fonctionne aussi, mais 'tr' est connu pour être problématique sur les distributions beaucoup plus âgés (environ Redhat 9-ish). tr est une abréviation pour « traduire », couramment utilisé dans les tubes pour transformer entrée. L'option -d signifie simplement « supprimer ».

La plupart des versions modernes contiennent également des macros prédéfinies pour transformer du haut en bas, inférieur à supérieur, tuer l'espace blanc, etc. Par conséquent, si vous l'utilisez, prenez une seconde pour se mêler à quoi d'autre il ne (voir la sortie d'aide / homme la page), est très pratique.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Explication: citations sont déjà comprises par le shell que vous pouvez demander au shell d'évaluer une commande qui echos juste la chaîne entre guillemets, de la même façon il le fait quand vous tapez vous-même

.

Ici, eval echo $VAR étend à eval echo 'FOOD' parce que les citations sont en fait une partie de la valeur de VAR. Si vous deviez exécuter echo 'FOOD' dans le shell que vous obtiendrez FOOD (sans les guillemets). Voilà ce que fait eval:. Il prend son entrée et elle fonctionne comme une commande shell

  

⚠CODE INJECTION!

     

eval exposer les scripts à l'injection de code.

     
VAR=';ls -l'

VAR=$(eval echo $VAR)
     

provoquera l'exécution de ls -l.

     

codes beaucoup plus dommageables pourraient être injectés ici.

Vous voulez probablement utiliser sed ...

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

Tout en utilisant builtins bash (à savoir l'expansion du paramètre 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 

Pour un autre exemple de voir d'extension des paramètres Bash:

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

Juste trébuché sur cela aussi. Pour les trois premiers cas de test, eval echo $string fonctionne bien. Pour le faire fonctionner pour tous les cas demandés et quelques autres, je suis venu avec cette (testé avec bash et 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)"

il ne gère pas les cas de pointe extrêmement bien (comme une chaîne vide), mais il servira de point de départ. Il fonctionne en entrelaçant le caractère avant et arrière si elles sont les mêmes et si elles sont "ou «

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top