Removendo aspas simples e duplas em uma string usando apenas comandos bash/padrão do Linux

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

  •  09-09-2019
  •  | 
  •  

Pergunta

Estou procurando algo que traduza uma string da seguinte maneira, usando apenas comandos bash/padrão do Linux:

  1. As aspas simples em torno de uma string devem ser removidas
  2. As aspas duplas em torno de uma string devem ser removidas
  3. Strings sem aspas devem permanecer as mesmas
  4. Strings com aspas vizinhas incomparáveis ​​devem permanecer as mesmas
  5. As aspas simples que não circundam a string devem permanecer
  6. As aspas duplas que não circundam a string devem permanecer

Por exemplo:

  • 'Alimento' deveria se tornar Alimento
  • “Comida” deveria se tornar Comida
  • A alimentação deve permanecer a mesma
  • 'Comida" deve permanecer a mesma
  • 'Comida' deve permanecer a mesma
  • 'Fo'od' deveria se tornar Fo'od
  • "Fo'od" deveria se tornar Fo'od
  • Fo'od deve permanecer o mesmo
  • 'Fo"od' deveria se tornar Fo"od
  • "Fo"od" deveria se tornar Fo"od
  • Fo"od deve permanecer o mesmo

Obrigado!

Foi útil?

Solução

Isso deve servir:

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

Onde in.txt está:

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

E esperado.txt é:

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

Você pode verificar se eles correspondem a:

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

Outras dicas

Você poderia usar tr:

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

...também funciona, no entanto, 'tr' é conhecido por ser problemático em distribuições muito mais antigas (por volta do Redhat 9-ish). tr é uma abreviatura de 'translate', comumente usada em pipes para transformar a entrada.O -d opção significa simplesmente 'excluir'.

A maioria das versões modernas também contém macros predefinidas para transformar superior em inferior, inferior em superior, eliminar espaços em branco, etc.Portanto, se você usá-lo, reserve um segundo para ver o que mais ele faz (consulte a saída de ajuda/página de manual), que é útil.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Explicação:Como as aspas já são compreendidas pelo shell, você pode pedir ao shell para avaliar um comando que apenas ecoa a string citada, da mesma forma que faz quando você mesmo digita.

Aqui, eval echo $VAR expande para eval echo 'FOOD' porque as cotações são na verdade parte do valor de VAR.Se você fosse correr echo 'FOOD' na casca que você obteria FOOD (sem as aspas).Isso é o que eval faz:ele pega sua entrada e a executa como um comando shell.

⚠INJEÇÃO DE CÓDIGO!

eval expor scripts à injeção de código.

VAR=';ls -l'

VAR=$(eval echo $VAR)

causará a execução de ls -l.

Códigos muito mais prejudiciais poderiam ser injetados aqui.

Você provavelmente deseja usar sed...

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

Apenas usando recursos internos do Bash (ou seja,Expansão do 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 

Para mais um exemplo de expansão de parâmetros Bash, consulte:

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

Apenas tropecei nisso também.Para os três primeiros casos de teste, eval echo $string funciona bem.Para fazê-lo funcionar em todos os casos solicitados e em alguns outros, criei isso (testado com 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)"

ele não lida muito bem com casos extremos (como uma string vazia), mas servirá como ponto de partida.Funciona distribuindo os caracteres da frente e de trás se eles forem iguais e se forem ' ou "

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top