Shell 脚本 - 从变量中删除第一个和最后一个引号 (")
Posted
技术标签:
【中文标题】Shell 脚本 - 从变量中删除第一个和最后一个引号 (")【英文标题】:Shell script - remove first and last quote (") from a variable 【发布时间】:2012-04-01 18:20:32 【问题描述】:下面是一个较大脚本的 shell 脚本的 sn-p。它从变量保存的字符串中删除引号。我正在使用 sed 执行此操作,但它有效吗?如果没有,那么有效的方法是什么?
#!/bin/sh
opt="\"html\\test\\\""
temp=`echo $opt | sed 's/.\(.*\)/\1/' | sed 's/\(.*\)./\1/'`
echo $temp
【问题讨论】:
我建议使用sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$opt"
。仅当存在匹配对时,此语法才会删除 qoutes。
@JohnSmith 我还必须在 shell 脚本中自动转义引号,但无论它们是否匹配,我都需要这样做,所以我可能不会使用你发布的那个表达式。
如果您只是想删除所有引号时发现此问题,请参阅此答案:askubuntu.com/a/979964/103498。
【参考方案1】:
使用tr删除"
:
echo "$opt" | tr -d '"'
注意:这会删除所有双引号,而不仅仅是前导和尾随。
【讨论】:
这不是 OP 要求的,因为它还会删除所有引号,而不仅仅是前导和尾随的。 虽然没有明确回答 OP,但这对我来说解决了,因为“/path/file-name”的开头和结尾只有双引号。没有嵌入的双引号。 +1 这个解决方案将是很多人想要的。在许多情况下,脚本可以很容易地将可用的数据转换为用引号括起来的字符串。 优雅并节省了我更多的试错调试时间。谢谢。 这是一个理想的人想要的,这就是为什么它比接受的答案有更多的选票。【参考方案2】:有一种更简单、更有效的方法,使用原生 shell 前缀/后缀去除功能:
temp="$opt%\""
temp="$temp#\""
echo "$temp"
$opt%\"
将删除后缀 "
(使用反斜杠转义以防止 shell 解释)。
$temp#\"
将删除前缀 "
(使用反斜杠转义以防止 shell 解释)。
另一个优点是它只会在有引号的情况下删除周围的引号。
顺便说一句,您的解决方案总是删除第一个和最后一个字符,无论它们可能是什么(当然,我确信您知道您的数据,但最好确定您要删除的内容)。
使用 sed:
echo "$opt" | sed -e 's/^"//' -e 's/"$//'
(改进版,如 jfgagne 所示,去掉了回声)
sed -e 's/^"//' -e 's/"$//' <<<"$opt"
因此,它将前导 "
替换为空,而尾随 "
也空替换。在同一个调用中(不需要管道和启动另一个 sed。使用 -e
您可以进行多个文本处理)。
【讨论】:
你可以用sed -e 's/^"//' -e 's/"$//' <<< $opt
去掉sed解决方案中的管道。
这可能会使字符串不具有前导和尾随引号字符。有什么优雅的处理建议吗?
要只处理匹配的外引号,请参阅@Joachim Pileborg 的答案
@jsears 嗯?如果有一个,这会从头开始修剪一个,如果有一个,则从结尾修剪一个。如果您不想删除,除非两者都存在;是的,可以使用单个 sed
正则表达式,或者可以将变量替换包装在 case $opt in '"'*'"') ... do it ... ;; esac
行中
你可以使用sed 's/^"\|"$//g'
避免多个表达式【参考方案3】:
如果您使用 jq 并尝试从结果中删除引号,则其他答案将起作用,但有更好的方法。通过使用-r
选项,您可以输出不带引号的结果。
$ echo '"foo": "bar"' | jq '.foo'
"bar"
$ echo '"foo": "bar"' | jq -r '.foo'
bar
【讨论】:
我正在使用jq
,但请注意,如果jq 也使用-a
输出ASCII 输出,则它不起作用(这是jq 方面的一个错误)
yq
也有-r
选项:yq -r '.foo' file.yml
【参考方案4】:
有一个简单的方法使用xargs:
> echo '"quoted"' | xargs
quoted
xargs 如果没有提供命令,则使用 echo 作为默认命令并从输入中去除引号。参见例如here.
【讨论】:
echo '"quoted"' | xargs
--> quoted
这有效,但仅适用于字符串中的偶数个引号。如果有奇数,则会产生错误。
最简单最优雅!谢谢。
为我工作,通过 terraform 使用。【参考方案5】:
最短路径 - 试试:
echo $opt | sed "s/\"//g"
它实际上从opt
中删除了所有"
s(双引号)(除了开头和结尾之外,真的会有更多的双引号吗?所以它实际上是同一件事,还有更多简短的;-))
【讨论】:
如果你想删除所有的双引号,那么最好使用:"$opt//\"/"。没有管道,没有子外壳......请注意,如果你opt中有空格,你可能会丢失它们。总是引用变量,如:echo "$opt" 嗯,这个变量基本上是从 httpd 的配置文件中读取 DocumentRoot 的路径,所以我不认为字符串中可能存在引号字符的情况。而且这个 sed 更加整洁和高效....谢谢!【参考方案6】:您只需拨打sed
即可:
$ echo "\"html\\test\\\"" | sed 's/^"\(.*\)"$/\1/'
html\test\
【讨论】:
【参考方案7】:Bash 中最简单的解决方案:
$ s='"abc"'
$ echo $s
"abc"
$ echo "$s:1:-1"
abc
这称为子字符串扩展(请参阅Gnu Bash Manual 并搜索$parameter:offset:length
)。在此示例中,它从s
中获取子字符串,该子字符串从位置 1 开始,到倒数第二个位置结束。这是因为如果length
是负值,则它被解释为从parameter
末尾的向后偏移。
【讨论】:
bash v4.2 支持的负长度【参考方案8】:更新
Stripping single and double quotes in a string using bash / standard Linux commands only 的简单而优雅的回答:
BAR=$(eval echo $BAR)
去掉 BAR
的引号。
================================================ ===============
根据hueybois的回答,经过反复试验,我想出了这个功能:
function stripStartAndEndQuotes
cmd="temp=\$$1%\\\""
eval echo $cmd
temp="$temp#\""
eval echo "$1=$temp"
如果您不想打印任何内容,可以通过管道将 eval 发送到 /dev/null 2>&1
。
用法:
$ BAR="FOO BAR"
$ echo BAR
"FOO BAR"
$ stripStartAndEndQuotes "BAR"
$ echo BAR
FOO BAR
【讨论】:
虽然我真的很喜欢简洁优雅,但我认为值得注意的是 eval 不只是做双引号修剪,而是实际评估为一行代码。因此,当 BAR 包含可能被 shell 替代的其他序列时(例如 BAR=\'abc\' 或 BAR=ab\'c 或 BAR=a\$b 或 BAR=a\$(ls *) )【参考方案9】:如果你来这里是为了 aws cli --query
,试试--output text
。
【讨论】:
完全来自 aws cli --query。谢谢! 对于 azure cli 使用--output tsv
哈哈哈。该死,这正是我想要的【参考方案10】:
这是不使用sed的最离散方式:
x='"fish"'
printf " quotes: %s\nno quotes: %s\n" "$x" "$x//\"/"
或者
echo $x
echo $x//\"/
输出:
quotes: "fish"
no quotes: fish
我是从 a source 那里得到的。
【讨论】:
这将删除字符串中的引号以及它周围的引号。 除注释外,与@StevenPenny's answer from 2012相同。【参考方案11】:Linux=`cat /etc/os-release | grep "ID" | head -1 | awk -F= ' print $2 '`
echo $Linux
Output:
"amzn"
从变量中删除双引号的最简单方法是
Linux=`echo "$Linux" | tr -d '"'`
Linux=$(eval echo $Linux)
Linux=`echo $Linux//\"/`
Linux=`echo $Linux | xargs`
All 提供不带双引号的输出:
回声 $Linux
amzn
【讨论】:
【参考方案12】:我知道这是一个非常古老的问题,但这是另一个 sed 变体,它可能对某人有用。与其他一些不同,它只替换开头或结尾的双引号...
echo "$opt" | sed -r 's/^"|"$//g'
【讨论】:
【参考方案13】:在 Bash 中,我会使用以下单行:
[[ "$str" == \"*\" || "$str" == \'*\' ]] && str="$str:1:-1"
这将删除周围的引号(单引号和双引号),同时保持字符串中的引号字符不变。此外,如果只有一个前导引号或只有一个尾随引号,它也不会做任何事情,这通常是我的经验所希望的。
封装在函数中:
#!/usr/bin/env bash
# Strip surrounding quotes from string [$1: variable name]
function strip_quotes()
local -n var="$1"
[[ "$var" == \"*\" || "$var" == \'*\' ]] && var="$var:1:-1"
str="$*"
echo "Before: $str"
strip_quotes str
echo "After: $str"
【讨论】:
【参考方案14】:我的版本
strip_quotes()
while [[ $# -gt 0 ]]; do
local value=$!1
local len=$#value
[[ $value:0:1 == \" && $value:$len-1:1 == \" ]] && declare -g $1="$value:1:$len-2"
shift
done
该函数接受变量名并在适当的位置去掉引号。它只去除一对匹配的前导和尾随引号。它不检查尾随引号是否被转义(前面是\
,它本身没有转义)。
根据我的经验,像这样的通用字符串实用函数(我有一个库)在直接操作字符串时最有效,不使用任何模式匹配,尤其是不创建任何子 shell,或调用任何外部sed
、awk
或 grep
等工具。
var1="\"test \\ \" end \""
var2=test
var3=\"test
var4=test\"
echo before:
for i in var1,2,3,4; do
echo $i="$!i"
done
strip_quotes var1,2,3,4
echo
echo after:
for i in var1,2,3,4; do
echo $i="$!i"
done
【讨论】:
【参考方案15】:还有另一种方法可以做到这一点。喜欢:
echo $opt:1:-1
【讨论】:
这个答案有already been given,另一个比较详细。【参考方案16】:我使用这个正则表达式,它可以避免从没有正确引用的字符串中删除引号:
echo '"only first' | sed 's/^"\(.*\)"$/\1/'
输出:>"只有第一个
echo 'only last"' | sed 's/^"\(.*\)"$/\1/'
输出:>“仅最后一个”
echo '"both"' | sed 's/^"\(.*\)"$/\1/'
输出:>两者
echo '"space after" ' | sed 's/^"\(.*\)"$/\1/'
输出:>“后面的空格”
echo ' "space before"' | sed 's/^"\(.*\)"$/\1/'
输出:>“之前的空格”
【讨论】:
【参考方案17】:如果您因为 Makefile 保留引号而尝试删除引号,请尝试以下操作:
$(subst $\",,$(YOUR_VARIABLE))
基于另一个答案:https://***.com/a/10430975/10452175
【讨论】:
$(subst ...)
是一个make
函数。 OP没有提到任何Makefile以上是关于Shell 脚本 - 从变量中删除第一个和最后一个引号 (")的主要内容,如果未能解决你的问题,请参考以下文章