読み込み可能なbashスクリプト
14289 ワード
私は、bashパイプラインを書く感じが本当に好きです.一緒にコマンドを文字列には、出力でピーク、私の目標に近いデータをマッサージする別のカップルパイプを追加するのは楽しい.私は、彼らに短いクラスさえ与えました:bgschiller/shell-challenges .
しかし、書くのが楽しいパイプラインが維持するのが苦痛であるとわかるのは簡単です.たとえ1ヶ月後に読んでいるとしても、それぞれの目的が何であるかを思い出すのは難しい.これはパイプラインをより読みやすいスクリプトの中間ファイルに壊すことを学んだトリックです.
仕事
私が取り組んでいる製品は“アラーム”のリストを持っている-エンドユーザーが警告する必要がある条件.また、各サポートされている言語のためのローカライズファイルは、人間の読み取り可能な名前、説明などのアラーム名をマップしています.アラームの多くは、それは難しいものは、すでに翻訳されて追跡するために十分です.これはスクリプトを呼び出します!
アラームファイルは次のようになります.
計画を立てる アラームからアラーム名を抽出します.XML使用 各アラームを事前にする必要があります 抽出する 用途 これはbashパイプラインを作る方法のポストではないので、私はその部分の上に光沢があります.ここに私が思い付いたものがあります.
一度に一歩
前のステップは我々が必要としたものを成し遂げました、しかし、それが起こっていたのを見るのはかなり難しかったです.私の意見では 名前は何もない.各プロセス置換は直接親に供給されるので、何もこれまでに名前を受け取りません.我々は、我々の中間体を命名する必要があります! コメントありません.すべての行がバックスラッシュで終わるのでコメントを追加するのは難しいです.bashは“この行を継続”とコメントを追加すると言うことができません. 中間ファイルを使って各部分をいじめるかどうか見てみましょう.
我々自身の後の浄化は、少しトリッキーです.理想的には、スクリプトが正常に終了したりクラッシュしたり、Ctrl - Cでキャンセルされるかどうかに関係なく、中間結果ファイルを配置しないようにします
しかし、書くのが楽しいパイプラインが維持するのが苦痛であるとわかるのは簡単です.たとえ1ヶ月後に読んでいるとしても、それぞれの目的が何であるかを思い出すのは難しい.これはパイプラインをより読みやすいスクリプトの中間ファイルに壊すことを学んだトリックです.
仕事
私が取り組んでいる製品は“アラーム”のリストを持っている-エンドユーザーが警告する必要がある条件.また、各サポートされている言語のためのローカライズファイルは、人間の読み取り可能な名前、説明などのアラーム名をマップしています.アラームの多くは、それは難しいものは、すでに翻訳されて追跡するために十分です.これはスクリプトを呼び出します!
アラームファイルは次のようになります.
<!-- Alarms.xml -->
<?xml version="1.0" encoding="utf-8"?>
<config name="AlarmConfig">
<AlarmList name="IngredientAlarms" version="1.0">
<Alarm name="MozzarellaTooWarm">
<!-- some alarm-specific stuff here -->
</Alarm>
<Alarm name="PizzaTooCold">
</Alarm>
<!-- ... -->
このようなローカライズ[{ stringId: "alarm_id_MozzarellaTooWarm",
localString: "MozzarellaTooWarm" },
{ stringId: "alarm_title_MozzarellaTooWarm",
localString: "Mozzarella Too Warm" },
{ stringId: "alarm_description_MozzarellaTooWarm",
localString: "The mozzarella has become too warm and must be used within the next five minutes" },
//...
]
計画を立てる
xpath
. alarm_id_
, alarm_title_
, alarm_description_
, alarm_operator_actions_
ローカライズファイルにマッチするために.それをするいくつかの方法を考え出す."stringId"
ローカライズファイルの各エントリから.ああ、しかし、ローカライズされる必要があるもののための他のエントリがあり、すべてのアラームではありません.それらをフィルタリングする方法を考え出す.おそらく使用jq
そのために.diff
キーを実際のキーで比較する.diff \
<(join -j 99999 \
<(echo 'alarm_id_
alarm_title_
alarm_description_
alarm_operator_actions_') \
<(xpath -q -e config/AlarmList/Alarm/@name Alarms.xml |
cut -d= -f2 | tr -d '"') \
| tr -d ' ' | sort) \
<(jq '.[] | select(.stringId | startswith("alarm_")) |
.stringId ' i18n/en.json | sort)
それは、そのような方法で畳み込まれて、ちょっと印象的です.しかし、コードを維持して満足しているでしょう.一度に一歩
前のステップは我々が必要としたものを成し遂げました、しかし、それが起こっていたのを見るのはかなり難しかったです.私の意見では
cat > alarm_attrs << EOF
alarm_id_
alarm_title_
alarm_description_
alarm_operator_actions_
EOF
xpath -q -e config/AlarmList/Alarm/@name Alarms.xml |
cut -d= -f2 | tr -d '"' > expected_alarm_names
join -j 999 alarm_attrs expected_alarm_names |
tr -d ' ' | sort > expected_localization_keys
jq -r '.[] | select(.stringId | startswith("alarm_")) |
.stringId' en.json | sort > actual_localization_keys
これはより良いです!各部分を分離して理解することができますし、ステップ間の依存関係を明示的に命名ファイルで追跡されます.すべての左側のコメントといくつかのエラーチェックを追加し、中間ファイルをクリーンアップすることです.我々自身の後の浄化は、少しトリッキーです.理想的には、スクリプトが正常に終了したりクラッシュしたり、Ctrl - Cでキャンセルされるかどうかに関係なく、中間結果ファイルを配置しないようにします
trap
これを扱うにはtrap
"signal "が発生したときに実行するコマンドを設定します.私たちはすべての中間ファイルをディレクトリと使用に置きますtrap
スクリプトを示す信号が火災終了時にそのディレクトリを削除します.#!/bin/bash
set -ef -o pipefail
readonly script_name=`basename "$0"`
usage() {
cat >&2 << EOF
Usage: $script_name <path-to-Alarms.xml> <path-to-en.json>
Compare the alarms specified in Alarms.xml against the
localizations keys provided in a [language-code].json file
(eg, en.json). Warn if any keys are missing or unexpected.
EOF
exit 2
}
if [[ $# != 2 ]]; then
echo "error: expected 2 arguments, received $#" 1>&2
usage
fi
readonly ALARM_CONFIG_XML=$1
if [[ ${ALARM_CONFIG_XML: -4} != ".xml" || ! -e $ALARM_CONFIG_XML ]]; then
echo "error: unable to find XML file at $ALARM_CONFIG_XML" 1>&2
usage
fi
readonly LOCALIZATION_JSON=$2
if [[ ${LOCALIZATION_JSON: -5} != ".json" || ! -e $LOCALIZATION_JSON ]]; then
echo "error: unable to find JSON file at $LOCALIZATION_JSON" 1>&2
usage
fi
# Make a directory for intermediate results
tmpdir=$(mktemp -d -p .)
# ensure it's removed when this script exits
trap "rm -rf $tmpdir" EXIT HUP INT TERM
# note: when debugging, turn off that `trap` line to keep
# intermediate results around
# The plan is ultimately to use diff to compare names between
# Alarms.xml and en.json. diff will tell us if any names
# appear in one file but are missing in the other (checks
# both directions for a mismatch).In pursuit of this, we need
# to create a couple of temporary files:
# 1) all the alarm names we expect to find (based on Alarms.xml)
# 2) all the names actually present in the localization file.
# A complication: the location file uses a flat format to
# store the id, title, description, and operator_actions:
# { "stringId": "alarm_id_MozzarellaTooWarm", ... },
# { "stringId": "alarm_title_MozzarellaTooWarm", ... },
# { "stringId": "alarm_description_MozzarellaTooWarm", ... },
# { "stringId": "alarm_operator_actions_MozzarellaTooWarm", ... },
# We want to check that *all* of these keys are present, so
# we use a cross product of (alarm names) X (those attributes)
cat > $tmpdir/alarm_attrs << EOF
alarm_id_
alarm_title_
alarm_description_
alarm_operator_actions_
EOF
xpath -q -e config/AlarmList/Alarm/@name $ALARM_CONFIG_XML |
cut -d= -f2 | tr -d '"' > $tmpdir/expected_alarm_names
# trick to compute cross product: use `join` with a join
# field that doesn't exist (999). since both files lack a
# field at 999, they will compare equal for every key, and
# each line of the left file will be joined with each line
# of the right file--a cross product.
join -j 999 $tmpdir/alarm_attrs $tmpdir/expected_alarm_names |
tr -d ' ' | sort > $tmpdir/expected_localization_keys
jq -r '.[] | select(.stringId | startswith("alarm_")) |
.stringId' $LOCALIZATION_JSON |
sort > $tmpdir/actual_localization_keys
if diff $tmpdir/expected_localization_keys $tmpdir/actual_localization_keys; then
echo "Success! Found all" $(wc -l $tmpdir/expected_localization_keys) "expected localization keys" 1>&2
else
echo "Failure. Found discrepancies between expected alarm names and actual localization keys" 1>&2
exit 1
fi
Reference
この問題について(読み込み可能なbashスクリプト), 我々は、より多くの情報をここで見つけました https://dev.to/bgschiller/readable-bash-scripts-41d3テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol