Stripping single and double quotes in a string using bash / standard Linux commands only

40,815

Solution 1

This should do it:

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

Where in.txt is:

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

And expected.txt is:

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

You can check they match with:

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

Solution 2

You could use tr:

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

... also works, however 'tr' is known to be problematic on much older (circa Redhat 9-ish) distributions. tr is an abbreviation for 'translate', commonly used in pipes to transform input. The -d option simply means 'delete'.

Most modern versions also contain predefined macros to transform upper to lower, lower to upper, kill white space, etc. Hence, if you use it, take a second to poke at what else it does (see the help output / man page), comes in handy.

Solution 3

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Explanation: Since quotes are already understood by the shell you can ask the shell to evaluate a command that just echos the quoted string, the same way it does when you type it yourself.

Here, eval echo $VAR expands to eval echo 'FOOD' because the quotes are actually part of the value of VAR. If you were to run echo 'FOOD' into the shell you'd get FOOD (without the quotes). That's what eval does: it takes its input and runs it like a shell command.

⚠CODE INJECTION!

eval expose scripts to code injection.

VAR=';ls -l'

VAR=$(eval echo $VAR)

will cause execution of ls -l.

Much more harmful codes could be injected here.

Solution 4

You probably want to use sed...

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

Solution 5

Just stumbled upon this as well. For the first three test cases, eval echo $string works well. To get it to work for all cases requested and a few others, I came up with this (tested with bash and 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"
Share:
40,815

Related videos on Youtube

Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm looking for something that will translate a string as follows, using only bash / standard Linux commands:

    1. Single-quotes surrounding a string should be removed
    2. Double-quotes surrounding a string should be removed
    3. Unquoted strings should remain the same
    4. Strings with unmatched surrounding quotes should remain the same
    5. Single-quotes that don't surround the string should remain
    6. Double-quotes that don't surround the string should remain

    For example:

    • 'Food' should become Food
    • "Food" should become Food
    • Food should remain the same
    • 'Food" should remain the same
    • "Food' should remain the same
    • 'Fo'od' should become Fo'od
    • "Fo'od" should become Fo'od
    • Fo'od should remain the same
    • 'Fo"od' should become Fo"od
    • "Fo"od" should become Fo"od
    • Fo"od should remain the same

    Thank you!

    • razlebe
      razlebe about 15 years
      +1 for all of those acceptance tests!
  • Admin
    Admin about 15 years
    This is very close, but just a teeny bit off. echo \"fo\"bar\' | sed -s "s/^(\"(.*)\")\|(\'(.*)\')\$‌​/\\2/g" Got: fobar' Expected: "fo"bar'
  • lhunath
    lhunath about 15 years
    Also, quote your parameter expansion.
  • Bhushan Kawadkar
    Bhushan Kawadkar almost 10 years
    please add some explanation too!!
  • Elliot Cameron
    Elliot Cameron about 7 years
    I added some explanation and modernized the example a bit.