다음과 같이 많은 파이프에서 작동하는 일련의 명령이 있습니다.
awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }' "/var/log/apache2/other_vhosts_access.log" | grep -v '127.0.0.1' | tr '[' '\0' | tr [:lower:] [:upper:] | sort -t' ' -s -k3
이는 기본적으로 Apache 로그를 필터링하고 세 개의 정보 열을 인쇄합니다. 첫 번째 열은 IP 주소, 두 번째 열은 시간, 세 번째 열은 문자열입니다. 출력은 모든 열을 기준으로 정렬될 수 있으므로 "-m"을 사용하여 시간 필드를 정렬해야 합니다. 정렬 순서를 반대로 할 수도 있습니다.
정렬할 매개변수를 저장하고 결합된 문자열이 실행되도록 하는 문자열을 원합니다. 이 같은:
$AWK_CMD | $SORT_CMD $SORT_KEY $SORT_REV
어디
SORT_CMD="sort -t' '"
SORT_KEY="-k$1" # $1 from cmd line arg
SORT_REV="$2" # Either -r or blank
이와 같은 문자열을 만들 수 있으면 괜찮아 보입니다. 문제는 실행 방법입니다. 다음과 같은 오류가 발생합니다.
awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }' "/var/log/apache2/other_vhosts_access.log" | grep -v '127.0.0.1' | tr '[' '\0' | tr [:lower:] [:upper:] | sort -t' ' -s -k3
Running ...
awk: '{
awk: ^ invalid char ''' in expression
정렬이 올바르게 정렬되지 않으면 무시하십시오. 이 문제는 해결될 수 있습니다. 최종 명령 문자열을 단계별로 작성하는 방법을 알고 싶습니다. 스크립트에서 이 명령을 실행하는 방법은 다음과 같습니다.
$final_cmd
`$final_cmd`
편집: 내가 사용해 본 스크립트
KEY=$1 # Values {1, 2, 3}
REVERSE=$2 # Values {0, 1}
SORT_CMD="sort -t' ' -s"
SORT_KEY="-k$KEY"
if [[ $KEY -eq 2 ]]
then
SORT_KEY="-m -k2"
fi
if [[ $REVERSE -eq 1 ]]
then
SORT_REV="-r"
else
SORT_REV=
fi
final_cmd="awk '{ if (\$8 ~ \"isad\") {print \$2, \$5, \"SE\"} else {print \$2, \$5, \"ANT\"} }' $LOG_FILE '|' grep -v '127.0.0.1' '|' tr '[' '\0' '|' tr [:lower:] [:upper:] '|' $SORT_CMD $SORT_KEY $SORT_REV"
echo $final_cmd
echo "Running ..."
$final_cmd
답변1
다양한 부분을 셸 함수에 넣을 수 있습니다.
awkfilter() {
awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }'
}
toupper() {
tr '[:lower:]' '[:upper:]'
}
dosort() {
sort -t' ' -s -k3
}
awkfilter < /var/log/apache2/other_vhosts_access.log |
grep -vF 127.0.0.1 |
tr '[' '\0' |
toupper |
dosort
그러면 선택 사항을 더 쉽게 만들 수 있습니다.
dosort() {
rev=
if [ "$2" = "reverse" ]
then
rev=-r
fi
sort -t' ' -s -k"$1" ${rev+"$rev"}
}
명령줄이 너무 길어지기 시작하면 스크립트로 작성하고 함수를 사용하여 여러 부분으로 나누는 것이 매우 도움이 되는 경우가 많습니다.
답변2
awk '{ ... }'
쉘 프롬프트나 쉘 스크립트에서 실행할 때 쉘은 따옴표를 구문 분석하고 awk
따옴표 없이 인수를 전달합니다. 무슨 일이 일어나든 매개 변수에 따옴표를 사용하여 실행하면 됩니다.
편집: 질문을 업데이트하면서 필요한 것은 입니다 sh -c "$final_cmd"
.
답변3
모든 경우에 변수에 옵션이 저장된 명령을 실행하려면 배열을 지원하는 셸을 사용하세요.
bash
예를 들어, 예제 코드는 다음과 같이 변환됩니다(변수 확장 등은 큰따옴표로 묶어야 함).
#!/bin/bash
key=$1 # Values {1, 2, 3}
reverse=$2 # Values {0, 1}
sort_key=()
if [ "$key" -eq 2 ]; then
sort_key=( -m )
fi
if [ "$reverse" -eq 1 ]; then
key+='r'
fi
sort_key+=( -k "$key" )
set -x
awk '$8 ~ "isad" { print $2, $5, ($8 ~ "isad" ? "SE" : "ANT") }' "$log_file" |
grep -Fv '127.0.0.1' |
tr '[:lower:][' '[:upper:]\0' |
sort -t ' ' -s "${sort_key[@]}"
이 특별한 경우에는 더 의미가 있을 수 있습니다.기능 사용그러나 배열은 예를 들어 스크립트의 자체 명령줄 인수를 수정하여 생성된 경로 이름이나 명령줄 인수의 수를 알 수 없는 경우에 유용합니다.
관련된: