要启动此脚本,需要使用shell bash、yaml截断以提高可读性,这是一个Github工作流。我已经尝试了很多事情使它作为多行工作,所以我可以有评论。
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这是我当前的错误
如果我把它作为一行运行,它就能正常工作。
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?
发布于 2021-03-11 18:23:50
您的主要问题是没有引用awk代码,这使得shell替换了代码中的$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可能会修改数据,这取决于shell的配置。
关于引用:见什么时候需要双重报价?
我在脚本中使用标准的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程序,我认为这样做与在单引号字符串中使用脚本相比没有任何额外的好处,如前面所示。它很混乱,除了两个需要执行的中心命令之外,还包含了许多用于维护的额外命令。
发布于 2021-03-11 19:43:34
将您的代码放在函数中,而不是变量中,类似这样的东西(未经测试,仍有改进的余地):
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发布于 2021-03-11 18:22:43
在我看来,最简单的方法(在可读性和可维护性方面)是将您的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}"https://unix.stackexchange.com/questions/638803
复制相似问题