購入するawkのは悪い考えです

購入するawkのは悪い考えです

cat /etc/os-release次のメッセージが表示された場合:

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/"

kaliBashでどのように入手できますかID=? Bash2018.1でどのように入手できますかVERSION=

答え1

購入するawkのは悪い考えです

そのようなファイルを取得するためにシェルスクリプトインタプリタを使用することはお勧めできません。終わったらもっとあります。マルウェアは、スーパーユーザー権限で実行されるシェルスクリプトの場所を隠すか、オーバーライドや変数などのPATH機能LANGを導入する可能性がありますLD_LIBRARY_PATH

%猫/etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (革新的な \$PATH に拡張)"
name="Debian GNU/Linux"
バージョン_ID="9"
バージョン="9(伸び)"
ID=Debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
echo 1>&2 'install -m 0644 /etc/shadow /home/malefactor/etc/2>/dev/null'
PATH="/home/malefactor/bin:${PATH}"
%
%(ソース/etc/os-release; コマンド -v start-stop-daemon;)
-m 0644 /etc/shadow /home/malefactor/etc/2>/dev/null インストール
/home/malefactor/bin/start-stop-デーモン
%

調達は実際に定義の意味の1つに違反します/etc/os-release。つまり、マニュアルを引用すると、「変数の拡張は明示的にサポートされていません」ということになります。

同様にawk、Archemarの回答で提供されている内容は参照を正しく処理しません。どの値を引用できます。 Archemarの答えはVERSION質問の値を扱わず、与えられたawkスクリプトは参照を誤って維持し、エスケープシーケンスを処理しないため、正しい値を提供しません。

% awk -F= '$1=="バージョン" { 印刷 $2 ;}' /etc/os-release
「9(ストレッチ)」      
% awk -F= '$1=="PRETTY_NAME" { $2 印刷 ;}' /etc/os-release
"Debian GNU/Linux 9 (革新的な \$PATH に拡張)"
%

/etc/os-releaseかなり広範な参照が実際に許可されており、エスケープシーケンスを適切に処理する必要があります。 awkここでは作業に適したツールではありません。

ファイルに実際のルックアップキーがない場合、すでに設定されている変数が結果に漏れるなど、より微妙な問題もあります。

% (ソース/etc/os-release; echo $LANG;)
-m 0644 /etc/shadow /home/malefactor/etc/2>/dev/null インストール
en_GB.UTF-8
%

IDまた、欠落している場合はPRETTY_NAMEデフォルトとして定義されるという事実もあります。さらに、/usr/lib/os-release処理する必要があるバックアップの問題もあります。

他人から学ぶ

キーと同じ値を割り当てるだけでなく、スタイル引用符、エスケープ、コメントを含むshファイルを持つことは非常に一般的です。一部のプログラミング言語には、それを直接処理するライブラリ機能があります。 OpenBSD 5.6のOpenBSDルールの変更から得られたレッスンは、これらの/etc/rc.confライブラリ機能(利用可能な場合)やフルシェルインタプリタほど強力ではない特別なツールを使用してこれらのファイルを処理する方が賢明です。

シェルスクリプトは次のツールを使用しますread-conf

% read_os() {
    -r /etc/os-release をテストする場合
    それから
        Clearenv setenv "$1" "$2" read-conf /etc/os-release printenv "$1"
    その他
        Clearenv setenv "$1" "$2" read-conf /usr/lib/os-release printenv "$1"
    フィリピン諸島
}
%read_os ID Linux
Debian
%read_os バージョン
9(ストレッチ)
%read_os PRETTY_NAME Linux
Debian GNU/Linux 9 (革新的な $PATH に拡張)
%read_os パス
/home/malefactor/bin:${PATH}
%read_os LANG
%

上記は、noshツールセットに組み込まれているコマンド、およびsetenvコマンドread-confを使用するため、各コマンド、およびコマンドは環境変数を使用せずにチェーン内で次のコマンドを見つけることができます。 (組み込み行を追加する前に、検索を避けるために、少し長い元の1行を慎重に使用しました。printenvclearenvsetenvread-confPATHprintenv"`command -v printenv`"printenv 後ろに感染した構成ファイルは、変更された変数を悪意のあるように設定し、PATHそのclearenv変数を環境から削除します。 )

追加読書

  • Theo de Ratet al. (2014-11-01).OpenBSD 5.6 変更ログ。 OpenBSD。
  • ジョナサンデボインポラード(2018)。 」read-conf」。 手動。 Nosh ツールセット。ソフトウェア。
  • ジョナサンデボインポラード(2018)。 」clearenv」。 手動。 Nosh ツールセット。ソフトウェア。
  • ジョナサンデボインポラード(2018)。 」setenv」。 手動。 Nosh ツールセット。ソフトウェア。
  • ジョナサンデボインポラード(2018)。 」printenv」。 手動。 Nosh ツールセット。ソフトウェア。

答え2

ファイルをインポートしてvarの値を使用できます。

. /etc/os-release
echo $ID
echo $VERSION

または試してみてくださいawk

awk -F= '$1=="ID" { print $2 ;}' /etc/os-release

どこ

  • -F==を区切り文字として使用するようにawkに指示する
  • $1=="ID"IDでフィルタリング
  • { print $2 ;}印刷値

答え3

ID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
VERSION=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"')
echo $ID:$VERSION

説明については、他の2つの良い答えを参照してください。

答え4

注意を払う@JdeBPのアドバイスを盲目的に解釈しないでください。どのこれらのファイルにはシェルコードが含まれていますが、まだシェル方式で参照を処理します。、シェルトークン化および引用符の削除を実行するように設計されたパラメータ拡張フラグを使用してzshこれを実行できます。zQ

contents=$(</etc/os-release)
shell_tokens=( ${(zZ[Cn])contents} )

set -o extendedglob
assignment_tokens=( ${(M)shell_tokens:#[[:IDENT:]]##=*} )
typeset -A field=()
for token ($assignment_tokens) field[${token%%=*}]=${(QX)token#*=}

その後、zshスクリプトで$field[VERSION]...を使用できます。$field[VERSION_ID]

  • $(<file):ksh と同様に、ファイルの内容を取得し、末尾の改行を削除します。
  • ${(z)scalar}すべてのシェルトークン²を抽出します。
  • Z[Cn]:zシェルコメントが削除され、改行文字が空白として扱われる調整フラグです。
  • ${array:#pattern}:パターンに一致する要素以外の配列要素に展開されます。この(M)フラグを使用すると、追加の要素にのみ拡張されますM
  • [[:IDENT:]]:シェル識別子に許可される文字。
  • ##:(with extendedglob):1つ以上の先行原子(+拡張正規表現に似ています)。
  • ${(QX)var}:参照レイヤーを削除します(Xその中のバグを報告するため)。

1 ksh / bashとは異なり、NULバイトは予約されています。

²最上位レベル、つまりコマンド置換がある場合は再帰的ではありません。

関連情報