Quando cat /etc/os-release
recebo o seguinte:
PRETTY_NAME="Kali GNU/Linux Rolling"
NAME="Kali GNU/Linux"
ID=kali
VERSION="2018.1"
VERSION_ID="2018.1"
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.kali.org/"
SUPPORT_URL="http://forums.kali.org/"
BUG_REPORT_URL="http://bugs.kali.org/"
Como eu pegaria kali
no ID=
bash? Como eu pegaria 2018.1
no VERSION=
bash?
Sourcing e
awk
são ideias ruinsFornecer esses tipos de arquivos com um interpretador de script de shell é uma má ideia, pois introduz outro local onde o malicioso pode ocultar o script de shell para ser executado com permissões de superusuário ou pode introduzir coisas como uma substituição de variáveis como
PATH
,LANG
eLD_LIBRARY_PATH
.Na verdade, o sourcing viola uma das semânticas definidas para
/etc/os-release
, que é (para citar seu manual) "a expansão variável não é explicitamente suportada".Da mesma forma,
awk
conforme fornecido na resposta de Archemar, não lida corretamente com citações; e qualquer valor pode ser cotado. Observe como a resposta de Archemar não aborda oVERSION
valor na pergunta, para o qual oawk
script fornecido não fornece o valor correto, porque retém erroneamente as aspas e não manipula as sequências de escape./etc/os-release
na verdade, é permitida uma latitude bastante ampla nas citações e também requer que as sequências de escape sejam processadas adequadamente.awk
não é realmente a ferramenta certa para o trabalho aqui.Existem outros problemas mais sutis, como vazamento de variáveis já definidas nos resultados se a chave real procurada estiver ausente do arquivo.
Há também o fato de que, se
ID
ouPRETTY_NAME
ausentes, são definidos como tendo valores padrão. E, além disso, há o recurso/usr/lib/os-release
para lidar.Aprendendo com outras pessoas
Arquivos que contêm atribuições chave-valor-igual, com
sh
aspas estilo -, escape e comentários, são bastante comuns. Algumas linguagens de programação possuem funções de biblioteca para lidar com elas diretamente. A lição da mudança das regras do/etc/rc.conf
OpenBSD no OpenBSD 5.6 é que é mais sensato usar tais funções de biblioteca, se disponíveis, ou ferramentas dedicadas que não chegam nem perto dos recursos de um interpretador de shell completo, para processar tais arquivos.A partir de scripts de shell, eu uso uma ferramenta chamada
read-conf
para processar esses arquivos:O mencionado acima depende de
setenv
,read-conf
eprintenv
comandos sendo comandos integrados no conjunto de ferramentas nosh, de modo queclearenv
,setenv
eread-conf
cada um encontre o próximo comando na cadeia sem usar aPATH
variável de ambiente. (Antes de adicionar o built-inprintenv
, os one-liners originais um pouco mais longos foram usados com cuidado"`command -v printenv`"
para evitar a pesquisaprintenv
após o arquivo de configuração infectado ter definido maliciosamente um alteradoPATH
e depoisclearenv
ter apagado essa variável do ambiente.)Leitura adicional
read-conf
". . _ conjunto de ferramentas nosh. Programas.clearenv
". . _ conjunto de ferramentas nosh. Programas.setenv
". . _ conjunto de ferramentas nosh. Programas.printenv
". . _ conjunto de ferramentas nosh. Programas.você pode originar o arquivo e usar o valor de var
ou tente com
awk
Onde
-F=
diga ao awk para usar = como separador$1=="ID"
filtrar no ID{ print $2 ;}
imprimir valorPara a explicação, veja as outras duas ótimas respostas:
Atendendo às recomendações de @JdeBP para não interpretar cegamente nenhum código shell nesses arquivos, mas ainda lidar com aspas da mesma forma que um shell faria , em
zsh
, você poderia fazer isso usando seus sinalizadores de expansão de parâmetroz
eQ
que são projetados para executar tokenização de shell e remoção de citação:Então, você pode usar
$field[VERSION]
,$field[VERSION_ID]
... em seu script zsh.$(<file)
: como em ksh: obtém o conteúdo do arquivo removido de todos os caracteres de nova linha à direita¹${(z)scalar}
extrai todos os tokens de shell².Z[Cn]
: ajuste oz
sinalizador, aqui para remover os comentários do shell e tratar a nova linha como apenas um espaço em branco.${array:#pattern}
: expande para os elementos da matriz, exceto aqueles que correspondem ao padrão. Com o(M)
sinalizador, expande apenas para osM
elementos anexados.[[:IDENT:]]
: caracteres permitidos em um identificador de shell.##
: (comextendedglob
): um ou mais dos átomos anteriores (como+
em expressões regulares estendidas).${(QX)var}
: remove uma camada de citação (X
para relatar erros lá).¹ tenha em atenção que, ao contrário do ksh/bash, os bytes NUL são preservados.
² os de nível superior, ou seja, não recursivamente se houver substituições de comandos, por exemplo.
Recentemente, tive que fazer algo semelhante e encontrei esta resposta. Talvez isso ajude:
A parte muito legal sobre isso é o arquivo
\K
. Simplesmente, ignore-o enquanto analisa o regex em sua cabeça. Depois de ver uma correspondência em uma linha, o resultado a ser exibido no terminal começará logo após o arquivo\K
.