bash 함수에 전달된 여러 문자열 인수가 있는데, 각 인수는 별도의 줄에 인쇄됩니다.
warn
첫 번째 매개변수부터 빨간색으로 인쇄된 줄 수만큼 값이 표시되도록 코드를 수정하고 싶습니다 ${@}
.
rge='^[0-9]+$'
if [[ -v warn && "$warn" == "1" ]]; then
printf '%s\n' ${red}"$1"${sgr} # first line red
printf '%s\n' "${@:2}" # remaining, uncoloured
elif [[ -v warn && "$warn" =~ $rge ]]; then
printf '%s\n' ${red}"$@"${sgr} # all lines red
fi
나는 첫 번째 시도로
elif [[ -v warn && "$warn" =~ $rge ]]; then
argc=$#
argv=("$@")
printf "%s\n" "argc: $argc"
for (( j=0; j<warn; j++ )); do
printf '%s\n' ${red}"${argv[j]}"${sgr}
done
#printf '%s\n' ${red}"$@"${sgr} # all lines red
fi
답변1
입력 줄 번호를 포함하여 다양한 조건에 따라 다양한 작업을 수행하는 방법을 이미 알고 있는 기존 도구를 활용하세요. 예를 들어 awk, sed, Perl, Python 등이 있습니다.
그런데 sh에서도 할 수 있는데 왜 그럴까요? 쉘 루프는 거의 항상 모든 형태의 텍스트 처리를 수행하는 최악의 방법입니다.
예를 들어, 아래에서는 셸을 사용하여 환경 변수를 설정한 다음 awk
색상 강조 표시를 수행합니다(a) 셸의 줄 수 계산 및 b) 읽기 루프 동안 셸을 사용하여 빠르고 어색하게 빠르고 간단한 작업을 수행하는 것을 방지합니다 awk
.
colourise() {
# colourise all (default) or the first N lines of stdin
# where N is the optional first argument to the function.
# check if arg is empty or numeric
[ -z "$1" ] || [[ "$1" =~ ^[0-9]+$ ]] \
|| echo "optional arg must be numeric if supplied" && exit 1
local colour="$(tput setaf 9)"
local sgr0="$(tput sgr0)"
awk -v c="$colour" -v s="$sgr0" -v w="$1" \
'(NR <= w || w == "") {print c $0 s; next}1'
}
그런데 awk 스크립트에서 직접 색상 코드와 sgr 코드를 하드코딩할 수 있습니다. 그런 다음 "$1" 값을 awk에 전달하면 됩니다(또는 export warn="$1"
쉘에서 awk에서 ENVIRON["warn"] 사용). 하지만 awk에는 기능이 없으므로 tput
이 작업을 수동으로 수행해야 합니다. 예를 들어, 다음은 vt100, ansi 또는 xterm과 같은 대부분의 터미널에서 작동합니다.
colourise() {
local warn="$1"
export warn
awk 'BEGIN {c="\033[91m"; s="\033[m\017"; w=ENVIRON["warn"]}
(NR <= w || w == "") {print c $0 s; next}1'
}
또는 (터미널의 하드코딩 이스케이프 시퀀스가 좋지 않기 때문에):
colourise() {
local warn="$1"
local colour="$(tput setaf 9)"
local sgr0="$(tput sgr0)"
export warn colour sgr0
awk 'BEGIN {c=ENVIRON["colour"]; s=ENVIRON["sgr0"]; w=ENVIRON["warn"]}
(NR <= w || w == "") {print c $0 s; next}1'
}
그런 다음 원하는 것을 colourise
함수에 파이프하십시오. 예를 들어
# colourise first three lines of an array
printf "%s\n" "${array[@]}" | colourise 3
# colourise all lines of head
head filename | colourise
# colourise only the first line of the output from several
# commands. use a compound command {} or a sub-shell ()
# this does not colourise the first line of each command separately,
# only the first line of the combined output.
{
command1
command2
command3
} | colourise 1
답변2
다음 문제가 해결되었습니다.
if [[ -v f ]] && (( f != 0 )); then
# print normal multi-line text
[[ ! -v warn ]] && printf '%s\n' "$@"
# print multi-line warnings
if [[ -v warn && "$warn" =~ $rge ]]; then
argc=$#
argv=("$@")
rge='^[0-9]+$'
(( warn > argc )) && warn=$argc
for (( j=0; j<argc; j++ )); do
(( j+1 <= warn )) && printf '%s\n' ${red}"${argv[j]}"${sgr}
(( j+1 > warn )) && printf '%s\n' "${argv[j]}"
done
#printf '%s\n' ${red}"$@"${sgr} # all lines red
fi
fi