简体   繁体   中英

Bash bad substitution with subshell

I am trying to get the Distro name without the quotation marks.

cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1

Returns: "CentOS Linux"

Now, using shell substitution, I tried to remove the quotation marks my placing the command in a sub-shell:

echo ${$(cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1)/\"}

I was thinking I could escape the quote using \\" and then omitting the last / to simply delete the quotes.

EDIT: I know this could be done with awk , but I don't know how.

EDIT: Output of 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)

Expected output: CentOS Linux

/etc/os-release appears to be a simple set of shell assignment statement; you might simply source it and output the value of $NAME (using a subshell to avoid potentially overwriting any variables in the current shell):

( . /etc/os-release; echo "$NAME" )

This might be a security risk, depending on your level of trust that /etc/os-release could contain other executable code for whatever reason.

Depending on your actual needs, you might also simply use /etc/centos-release , which contains the information you want as a simple string. (You might not be assuming that your script will run on a CentOS box, of course. os-release appears to be a more distro-agnostic version.)

Using awk , getting the OS name following the NAME variable.

awk -F"=" '$1=="NAME"{gsub(/"/, "", $2);print $2; exit}' /etc/os-release 
CentOS Linux

Your solution almost works. The quotes in "CentOS Linux" were part of the release-file, using a subshell doesn't help. You can use cut with a double quote as delimiter:

cat /etc/*-release | grep "NAME=.*" -o | cut -d "=" -f2 | head -n1 | cut -d '"' -f2

You can do the same using sed with

sed -n '/^NAME=/ {s/NAME="\(.*\)".*/\1/p;q}' /etc/*-release 

Explanation: Tell sed only to print lines asked for with a p , look for a line starting with NAME= , match the part between the quotes and quit after the first line with NAME= .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM