Bash 用 subshell 替换错误
Bash bad substitution with subshell
我正在尝试获取不带引号的发行版名称。
cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1
Returns:
"CentOS Linux"
现在,使用 shell 替换,我试图删除引号我将命令放在子 shell:
echo ${$(cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1)/\"}
我想我可以使用 \"
转义引号,然后省略最后一个 /
以简单地删除引号。
编辑:
我知道这可以用 awk
来完成,但我不知道怎么做。
编辑:
cat /etc/*-release
的输出:
CentOS Linux release 7.2.1511 (Core)
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
CentOS Linux release 7.2.1511 (Core)
CentOS Linux release 7.2.1511 (Core)
预期输出:CentOS Linux
/etc/os-release
看起来是一组简单的 shell 赋值语句;你 可能 简单地获取它并输出 $NAME
的值(使用 subshell 以避免可能覆盖当前 shell 中的任何变量):
( . /etc/os-release; echo "$NAME" )
这可能存在安全风险,具体取决于您对 /etc/os-release
可能出于任何原因包含其他可执行代码的信任程度。
根据您的实际需要,您也可以简单地使用/etc/centos-release
,它包含您想要的信息作为一个简单的字符串。 (当然,您可能不会假设您的脚本会 运行 在 CentOS 机器上。os-release
似乎是一个更 distro-agnostic 的版本。)
使用 awk
,获取 NAME
变量后的 OS 名称。
awk -F"=" '=="NAME"{gsub(/"/, "", );print ; exit}' /etc/os-release
CentOS Linux
您的解决方案几乎可行。 "CentOS Linux"
中的引号是 release-file 的一部分,使用子 shell 没有帮助。您可以使用 cut
和双引号作为分隔符:
cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1 | cut -d '"' -f2
您可以使用 sed
和
来做同样的事情
sed -n '/^NAME=/ {s/NAME="\(.*\)".*//p;q}' /etc/*-release
解释:告诉 sed
只打印 p
要求的行,寻找以 NAME=
开头的行,匹配引号之间的部分并在第一个之后退出符合 NAME=
.
我正在尝试获取不带引号的发行版名称。
cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1
Returns:
"CentOS Linux"
现在,使用 shell 替换,我试图删除引号我将命令放在子 shell:
echo ${$(cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1)/\"}
我想我可以使用 \"
转义引号,然后省略最后一个 /
以简单地删除引号。
编辑:
我知道这可以用 awk
来完成,但我不知道怎么做。
编辑:
cat /etc/*-release
的输出:
CentOS Linux release 7.2.1511 (Core)
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
CentOS Linux release 7.2.1511 (Core)
CentOS Linux release 7.2.1511 (Core)
预期输出:CentOS Linux
/etc/os-release
看起来是一组简单的 shell 赋值语句;你 可能 简单地获取它并输出 $NAME
的值(使用 subshell 以避免可能覆盖当前 shell 中的任何变量):
( . /etc/os-release; echo "$NAME" )
这可能存在安全风险,具体取决于您对 /etc/os-release
可能出于任何原因包含其他可执行代码的信任程度。
根据您的实际需要,您也可以简单地使用/etc/centos-release
,它包含您想要的信息作为一个简单的字符串。 (当然,您可能不会假设您的脚本会 运行 在 CentOS 机器上。os-release
似乎是一个更 distro-agnostic 的版本。)
使用 awk
,获取 NAME
变量后的 OS 名称。
awk -F"=" '=="NAME"{gsub(/"/, "", );print ; exit}' /etc/os-release
CentOS Linux
您的解决方案几乎可行。 "CentOS Linux"
中的引号是 release-file 的一部分,使用子 shell 没有帮助。您可以使用 cut
和双引号作为分隔符:
cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1 | cut -d '"' -f2
您可以使用 sed
和
sed -n '/^NAME=/ {s/NAME="\(.*\)".*//p;q}' /etc/*-release
解释:告诉 sed
只打印 p
要求的行,寻找以 NAME=
开头的行,匹配引号之间的部分并在第一个之后退出符合 NAME=
.