このスクリプトを開始するには、シェルbashを使用してGithubワークフローを実行し、読みやすくするためにyamlを切り捨てます。私はコメントを付けることができるように複数行で動作するように多くの努力をしました。
set -x
set -e
AWK_SOURCE=$( cat <<- AWK
'
{
if ( $1 !~ /delete/ # ensure we are not trying to process deleted files
&& $4 !~ /theme.puml|config.puml/ # do not try to process our theme or custom config
&& $4 ~ /.puml/ ) # only process puml files
{ printf "%s ", $4 } # only print the file name and strip newlines for spaces
}
END { print "" } # ensure we do print a newline at the end
'
AWK
)
GIT_OUTPUT=`git diff-tree -r --no-commit-id --summary ${GITHUB_SHA}`
AWK_OUPUT=`echo $GIT_OUTPUT | awk -F' ' $AWK_SOURCE`
echo "::set-output name=files::$GIT_OUTPUT"
set +e
set +x
これは私の現在のエラーです
これを1行で実行するとうまくいきます。
git diff-tree -r --no-commit-id --summary HEAD | awk -F' ' '{ if ( $1 !~ /delete/ && $4 !~ /theme.puml|config.puml/ && $4 ~ /.puml/ ) { printf "%s ", $4 } } END { print "" }'
これは現在表示されている出力/エラーです。他の出力/エラーが表示されます。
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
+ set -e
++ cat
+ AWK_SOURCE=''\''
{
if ( !~ /delete/ # ensure we are not trying to process deleted files
&& !~ /theme.puml|config.puml/ # do not try to process our theme or custom config
&& ~ /.puml/ ) # only process puml files
{ printf "%s ", } # only print the file name and strip newlines for spaces
}
END { print "" } # ensure we do print a newline at the end
'\'''
++ git diff-tree -r --no-commit-id --summary 6c72c8a8dabf19ae2439ee506b9a4a636027193e
+ GIT_OUTPUT=' create mode 100644 .config/plantuml/config.puml
create mode 100644 .config/plantuml/theme.puml
delete mode 100644 config.puml
create mode 100644 docs/README.md
create mode 100644 docs/domain-model/README.md
create mode 100644 docs/domain-model/user.md
create mode 100644 docs/domain-model/user.puml
delete mode 100644 theme.puml
delete mode 100644 user.puml
delete mode 100644 user.svg'
++ echo create mode 100644 .config/plantuml/config.puml create mode 100644 .config/plantuml/theme.puml delete mode 100644 config.puml create mode 100644 docs/README.md create mode 100644 docs/domain-model/README.md create mode 100644 docs/domain-model/user.md create mode 100644 docs/domain-model/user.puml delete mode 100644 theme.puml delete mode 100644 user.puml delete mode 100644 user.svg
++ awk '-F ' \' '{' if '(' '!~' /delete/ '#' ensure we are not trying to process deleted files '&&' '!~' '/theme.puml|config.puml/' '#' do not try to process our theme or custom config '&&' '~' /.puml/ ')' '#' only process puml files '{' printf '"%s' '",' '}' '#' only print the file name and strip newlines for spaces '}' END '{' print '""' '}' '#' ensure we do print a newline at the end \'
awk: cmd. line:1: '
awk: cmd. line:1: ^ invalid char ''' in expression
+ AWK_OUPUT=
コメント付きの複数行awkを維持する方法は?
答え1
次のように変数ではなく関数にコードを入れます(テストされていませんが、まだ改善の余地があります)。
set -x
set -e
do_awk() {
awk '
($1 !~ /delete/) && # ensure we are not trying to process deleted files
($4 !~ /theme.puml|config.puml/) && # do not try to process our theme or custom config
($4 ~ /.puml/) { # only process puml files
printf "%s ", $4 # only print the file name and strip newlines for spaces
}
END { print "" } # ensure we do print a newline at the end
' "${@:--}"
}
GIT_OUTPUT=$(git diff-tree -r --no-commit-id --summary "$GITHUB_SHA")
AWK_OUPUT=$(printf '%s\n' "$GIT_OUTPUT" | do_awk)
echo "::set-output name=files::$GIT_OUTPUT"
set +e
set +x
答え2
主な問題は、コードが引用されていないため、シェルがawk
コードの内容を置き換えることができることです。$4
シェルからコードを保護するには、ここにドキュメントを引用してください。開始区切り文字を引用符(<<'AWK'
またはのように<<"AWK"
)で囲むかエスケープして、ここから文書を引用することができます<<\AWK
。
私が書いた方法でスクリプトを再構築すると、次のようになります。
git diff-tree -r --no-commit-id --summary "$GITHUB_SHA" |
awk '
$1 !~ /^delete/ && $4 !~ /(theme|config)\.puml$/ && $4 ~ /\.puml$/ {
name[++n] = $4
}
END {
$0 = ""
for (i in name) $i = name[i]
printf "::set-output name=files::%s\n", $0
}'
中間データを変数に保存しないことに注意してください。これは非効率的です(わからないかもしれません)。どのくらい変数に格納されたデータが必要で、引用エラーが発生しやすい。代わりに、スペースに値を吐き出し、ファイル名のグロービングを呼び出します。この点で$GIT_OUTPUT
引用符を使用または使用しないことは問題になり、シェル構成によってバックスラッシュが含まれているとデータが変更される可能性があるため特に問題になります。$AWK
echo $GIT_OUTPUT
echo
引用について:参照いつ二重引用符が必要ですか?
解析したい文字列を含むpattern { action }
配列を作成するために、スクリプトは標準構文を使用しています。name
このEND
ブロックは出力レコードを生成し、$0
出力に使用したプレフィックスを使用して出力しますecho
。
これにより、コメントを作成できるスペースが増えます。
git diff-tree -r --no-commit-id --summary "$GITHUB_SHA" |
awk '
$1 ~ /^delete/ {
# skip these
next
}
$4 ~ /(theme|config)\.puml$/ {
# and these...
next
}
$4 ~ /\.puml$/ {
# pick out filename (we assume no whitespace in filenames)
name[++n] = $4
}
END {
$0 = ""
for (i in name) $i = name[i]
printf "::set-output name=files::%s\n", $0
}'
ここにある文書にソースコードを挿入するには、awk
次の手順を実行します。
awk_script=$(mktemp) || exit 1
trap 'rm -f "$awk_script"' EXIT
cat <<'AWK_CODE' >"$awk_script"
$1 !~ /^delete/ && $4 !~ /(theme|config)\.puml$/ && $4 ~ /\.puml$/ {
name[++n] = $4
}
END {
$0 = ""
for (i in name) $i = name[i]
printf "::set-output name=files::%s\n", $0
}
AWK_CODE
git diff-tree -r --no-commit-id --summary "$GITHUB_SHA" |
awk -f "$awk_script"
つまり、後で呼び出され、スクリプトの最後から削除される一時ファイルawk
にスクリプトを保存します(ここで使用されます)。ただし、このようなショートプログラムの場合、一重引用符で囲まれた文字列にスクリプトを使用するのと比較してこれを行うことには追加の利点はありません(最初の参照)。混乱し、多くの内容が含まれています。awk -f
trap
awk
追加コマンド実行する必要がある2つの中央コマンドを除いて、メンテナンスにのみ使用されます。
答え3
読みやすさとメンテナンスの面で最も簡単な方法は、awk
スクリプトを一時ファイルに送信してから次のようにインポートすることですawk
。
awksrc=$(mktemp) || exit 1
cat << 'EOF' > "${awksrc}"
{
if ( $1 !~ /delete/ # ensure we are not trying to process deleted files
&& $4 !~ /theme.puml|config.puml/ # do not try to process our theme or custom config
&& $4 ~ /.puml/
) # only process puml files
{ printf "%s ", $4 } # only print the file name and strip newlines for spaces
}
END { print "" } # ensure we do print a newline at the end
EOF
echo "$GIT_OUTPUT" | awk -f "${awksrc}"
rm -f "${awksrc}"
答え4
私はGitHub Workflowを使ったことがありませんが、文書によるとカスタムシェルを使用できます。あなたが言うなら:
steps:
- name: process puml files
run: <your awk script here>
shell: awk -f {0}
または、その一部の置換を使用すると、シェルを無駄にせずにraw awkスクリプトを実行できる必要があります。