仅使用bash /标准Linux命令在string中剥离单引号和双引号

我正在寻找的东西,将如下翻译一个string,只使用bash /标准的Linux命令:

  1. 围绕string的单引号应该被删除
  2. 应该删除string周围的双引号
  3. 未加引号的string应该保持不变
  4. 无与伦比的周边报价string应保持不变
  5. 不包围string的单引号应该保留
  6. 应该保留不包围string的双引号

例如:

  • “食物”应该成为食物
  • “食物”应成为食物
  • 食物应该保持不变
  • “食物”应该保持不变
  • “食物”应该保持不变
  • “Fo'od”应该变成Fo'od
  • “Fo'od”应该变成Fo'od
  • Fo'od应该保持不变
  • 'Fo'od'应该变成Fo'od
  • “Fo”od“应该变成Fo”
  • 佛罗里达州应该保持不变

谢谢!

Solutions Collecting From Web of "仅使用bash /标准Linux命令在string中剥离单引号和双引号"

这应该做到这一点:

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

其中in.txt是:

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

而且expected.txt是:

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

你可以检查他们是否匹配:

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

你可以使用tr

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

…也有效,但是“tr”在更老的(大约Redhat 9-ish)发行版中已知是有问题的。 tr是“translate”的缩写,通常用于管道来转换输入。 -d选项只是表示“删除”。

大多数现代版本还包含预定义的宏,可以将上下变换为下,上下变为上,杀死空白等。因此,如果使用它,请花点时间捅一下它还做了什么(请参阅帮助输出/手册页),派上用场。

你可能想使用sed

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

说明:由于shell已经理解了引号,因此可以让shell评估一个与引用的字符串相同的命令,这与您自己输入引用的字符串的方式相同。

在这里, eval echo $VAR扩展为eval echo 'FOOD'因为引用实际上是VAR值的一部分。 如果你运行echo 'FOOD'到shell中,你会得到FOOD (没有引号)。 这就是eval所做的:它接受它的输入并像shell命令一样运行它。

只需使用Bash内建函数(即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 

有关Bash参数扩展的另一个示例,请参阅:

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

刚刚偶然发现了这个。 对于前三个测试用例, eval echo $string效果很好。 为了让它适用于所有的要求和其他一些案件,我想出了这个(测试与bashdash ):

 #!/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 'ooo' 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)" 

它不能很好地处理边界情况(如空字符串),但它将作为一个起点。 如果它们是相同的,并且如果它们是“或”