이 스크립트를 시작하려면 쉘 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
이것은 나의 현재 오류입니다
이것을 한 줄로 실행하면 잘 작동합니다.
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
추가 명령실행해야 하는 두 개의 중앙 명령을 제외하고 유지 관리용으로만 사용됩니다.
답변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}
또는 그것의 일부 순열을 사용하면 쉘 헛소리 없이 원시 awk 스크립트를 실행할 수 있어야 합니다.