Strippen Sie einzelne und doppelte Zitate in einer Zeichenfolge nur mit Bash / Standard -Linux -Befehlen

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

  •  09-09-2019
  •  | 
  •  

Frage

Ich suche etwas, das eine Zeichenfolge wie folgt übersetzt und nur Bash / Standard -Linux -Befehle verwendet:

  1. Ein-Zitate, die eine Schnur umgeben, sollten entfernt werden
  2. Die umgebende Doppelquote, die eine Schnur umgeben, sollten entfernt werden
  3. Nicht zahlte Saiten sollten gleich bleiben
  4. Saiten mit unübertroffenen umgebenden Zitaten sollten gleich bleiben
  5. Ein-Zitate, die die Saite nicht umgeben, sollten bleiben
  6. Doppelquote, die die Saite nicht umgeben, sollte bleiben

Zum Beispiel:

  • "Essen" sollte zu Essen werden
  • "Essen" sollte zu Essen werden
  • Essen sollte gleich bleiben
  • 'Essen' sollte gleich bleiben
  • "Essen" sollte gleich bleiben
  • 'Fo'od' sollte für Fo'od werden
  • "Fo'od" sollte fo'od werden
  • Fo'od sollte gleich bleiben
  • 'Fo "od' sollte für zu werden" od
  • "Fo" od "sollte fo" od werden
  • Fo "od sollte gleich bleiben

Vielen Dank!

War es hilfreich?

Lösung

Dies sollte es tun:

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

Wo in.txt ist:

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

Und erwartet.txt ist:

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

Sie können überprüfen, ob sie übereinstimmen:

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

Andere Tipps

Du könntest benutzen tr:

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

... auch funktioniert, aber "tr" ist jedoch als problematisch bei viel älteren (Circa Redhat 9-ISH) -Verteilungen bekannt. tr ist eine Abkürzung für "Translate", die üblicherweise in Rohren verwendet wird, um die Eingabe zu transformieren. Das -d Option bedeutet einfach 'löschen'.

Die meisten modernen Versionen enthalten auch vordefinierte Makros, um die obere nach unten nach unten nach oben nach oben zu transformieren, den weißen Raum abzutöten usw., wenn Sie ihn verwenden, nehmen Sie sich eine Sekunde Zeit, um zu stöbern, was es sonst noch tut (siehe Hilfeseiten / Mannseite). kommt nützlich.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Erläuterung: Da Zitate bereits von der Shell verstanden werden, können Sie die Shell bitten, einen Befehl zu bewerten, der nur die zitierte Zeichenfolge wiederholt, genauso wie sie es selbst eingeben.

Hier, eval echo $VAR erweitert zu eval echo 'FOOD' Weil die Zitate tatsächlich Teil des Wertes von sind VAR. Wenn Sie rennen würden echo 'FOOD' in die Hülle, die du bekommen würdest FOOD (ohne die Anführungszeichen). Das ist, was eval tut: Es nimmt seine Eingabe und führt es wie ein Shell -Befehl aus.

⚠Code Injection!

eval Stellen Sie Skripte für die Codeinjektion aus.

VAR=';ls -l'

VAR=$(eval echo $VAR)

wird die Ausführung von verursachen ls -l.

Hier könnten viel schädlichere Codes injiziert werden.

Sie möchten wahrscheinlich verwenden sed...

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

Verwenden Sie nur BASH -BAHRE (dh Bash -Parameterausdehnung):

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 

Für ein weiteres Beispiel für eine Bash -Parameterausdehnung siehe:

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

Ich bin gerade auch darauf gestoßen. In den ersten drei Testfällen,, eval echo $string funktioniert gut. Damit es für alle angeforderten und ein paar anderen Fälle funktioniert, habe ich mich ausgedacht (getestet mit bash und 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)"

Es handelt sich nicht um Kantenfälle (z. B. eine leere Schnur), aber es wird als Ausgangspunkt dienen. Es funktioniert, indem es den vorderen und hinteren Charakter streift, wenn sie gleich sind und ob sie 'oder "sind

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top