Spogliarello virgolette singole e doppie in una stringa utilizzando bash / solo i comandi standard di Linux

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

  •  09-09-2019
  •  | 
  •  

Domanda

Sto cercando qualcosa che tradurre una stringa come segue, utilizzando solo bash / comandi standard di Linux:

  1. singole virgolette che circondano una stringa dovrebbero essere rimossi
  2. virgolette che circondano una stringa dovrebbero essere rimossi
  3. stringhe non quotati dovrebbero rimanere gli stessi
  4. stringhe con le virgolette che circondano senza eguali dovrebbe rimanere lo stesso
  5. Single-citazioni che non circondano la stringa dovrebbe rimanere
  6. virgolette che non circondano la stringa dovrebbe rimanere

Ad esempio:

  • 'Food' dovrebbe diventare alimentare
  • "Food" dovrebbe diventare alimentare
  • Il cibo dovrebbe rimanere lo stesso
  • 'Food" dovrebbe rimanere lo stesso
  • "Food' dovrebbe rimanere lo stesso
  • 'Fo'od' dovrebbe diventare Fo'od
  • "Fo'od" dovrebbe diventare Fo'od
  • Fo'od dovrebbe rimanere lo stesso
  • 'Fo "od' dovrebbe diventare Fo" od
  • "Fo" od "dovrebbe diventare Fo" od
  • Fo "od dovrebbe rimanere lo stesso

Grazie!

È stato utile?

Soluzione

Questo dovrebbe farlo:

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

Dove in.txt è:

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

E expected.txt è:

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

È possibile controllare che corrispondano con:

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

Altri suggerimenti

È possibile utilizzare tr:

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

... funziona anche, però 'tr' è noto per essere problematico su gran parte anziani (circa Redhat 9-ish) distribuzioni. tr è l'abbreviazione di 'tradurre', comunemente utilizzati in tubazioni per trasformare ingresso. L'opzione -d significa semplicemente 'delete'.

La maggior parte delle versioni moderne contengono anche macro predefinite per trasformare superiore a quella inferiore, inferiore a superiore, di uccidere uno spazio bianco, ecc Quindi, se lo si utilizza, prendere un secondo a colpire in che altro lo fa (vedi l'aiuto di uscita / uomo pagina), è utile.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Spiegazione: Dal momento che citazioni sono già comprese dalla shell è possibile chiedere il guscio per valutare un comando che solo echos la stringa tra virgolette, allo stesso modo in cui funziona quando si digita da soli

.

Qui, eval echo $VAR espande per eval echo 'FOOD' perché le quotazioni sono in realtà parte del valore della VAR. Se si dovesse eseguire echo 'FOOD' nella shell si otterrebbe FOOD (senza le virgolette). Questo è ciò che fa eval:. Prende il suo ingresso e lo esegue come un comando di shell

  

⚠CODE INIEZIONE!

     

eval esporre gli script per l'iniezione di codice.

     
VAR=';ls -l'

VAR=$(eval echo $VAR)
     

causerà esecuzione ls -l.

     

molto più dannosi codici potrebbero essere iniettati qui.

Probabilmente si desidera utilizzare sed ...

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

Proprio utilizzando builtins Bash (vale a dire Bash espansione di parametro):

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 

Per l'ennesimo esempio di Bash espansione di parametro vedi:

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

Proprio imbattuto in questo pure. Per i primi tre casi di test, eval echo $string funziona bene. Per farlo funzionare per tutti i casi richiesti e pochi altri, sono arrivato fino a questo (testato con bash e 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)"

non gestisce casi limite estremamente bene (come una stringa vuota), ma servirà come punto di partenza. Funziona striping carattere anteriore e posteriore se sono lo stesso e se sono 'o "

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top