grep
동일한(매우 긴) 명령을 여러 번 반복하는 스크립트가 있습니다. 줄 길이를 줄여서 스크립트를 더 읽기 쉽게 만들고 싶어서 명령어의 일부를 변수에 넣어보았습니다.
다음 줄은 다음과 같습니다(다른 매개변수를 사용하여 스크립트에서 여러 번 반복됨).
rsync -av --delete -R --exclude=alternatives /etc/ /backup.raw/ | grep -E '^deleting|[^/]$' >> /var/log/rsync.log
그 라인은 잘 작동합니다. 나는 그것을 다음과 같이 축약해 보았습니다.
_rscmd='rsync -av --delete -R'
_mn=/backup.raw/
_grep='grep -E "^deleting|[^/]$"'
_rslog=/var/log/rsync.log
따라서 "마지막" 줄은 다음과 같을 수 있습니다.
$_rscmd --exclude=alternatives /etc/ $_mn | $_grep >> $_rslog
그러나 그 줄은 $_grep
변수에서 실패합니다. 어떻게 하면 올바르게 쓸 수 있나요? 나는 성공 "…"
하지 '…'
못했습니다. grep 명령은 원래 작동했습니다.
답변1
변수를 사용하는 경우 여러 부분(명령 및 매개변수)으로 분할하는 것이 작동하지 않습니다. 이 예의 경우 eval
:
eval $_rscmd --exclude=alternatives /etc/ $_mn | eval $_grep >> "$_rslog"
일반적으로 사용하는 것이 가장 좋습니다.쉘 기능또는별명 변수를 사용하는 것보다:
alias my_grep='grep -E "^deleting|[^/]$"'
...
... | my_grep >> "$_rslog"
답변2
일반적인 접근 방식은 명령의 매개변수를 변수로 설정하는 것입니다.
_mn=/backup.raw/
_rscmdarg='-av --delete -R'
_greparg='-E "^deleting|[^/]$"'
_rslog=/var/log/rsync.log
$_rslog
파일이나 디렉터리와 마찬가지로 $_mn
보관해도 괜찮습니다.
"마지막" 줄은 다음과 같습니다:
rsync $_rscmdarg --exclude=alternatives /etc/ $_mn | grep $_greparg >> $_rslog
답변3
다른 두 답변의 가장 좋은 부분을 통합하는 한 가지 방법(IMHO)은 변경하지 않고 원하는 모든 기능을 포함하고 다양한 상황에서 달라지려는 기능을 지정하는 인수를 사용하는 쉘 함수를 작성하는 것입니다. 예:
my_rsync_grep() {
rsync -av --delete -R "$1" "$2" "$3" | grep -E '^deleting|[^/]$' >> /var/log/rsync.log
}
필수 매개변수를 사용하여 호출하세요.
my_rsync_grep --exclude=alternatives /etc/ /backup.raw/
rsync … | grep …
이는 명령을 별도의 스크립트에 넣은 것과 같습니다 . (단, 별도의 파일이 아니므로 여러 파일을 추적하는 구성 관리 문제나 다른 스크립트를 호출하는 방법에 대한 논리 문제(예: ? 를 사용합니까?)가 없으며 ./
함수를 매번 호출하지 않습니다. 추가 디스크 I/O가 발생하지 않습니다.)
노트:
가독성과 프로그래밍 스타일의 이유로 I/O 리디렉션(
>> /var/log/rsync.log
)을 함수 밖으로 이동하여 모든 호출에 적용할 수 있습니다.my_rsync_grep --exclude=alternatives /etc/ /backup.raw/ >> /var/log/rsync.log
이렇게 하면 스크립트를 읽거나 유지 관리하는 사람에게 해당 줄이 파일에 기록되고 있음이 분명해집니다. 그러나 스크립트에 실수로 불일치가 발생하기가 더 쉬워집니다. 물론 파일 이름을 변수(예: )에 넣어서
$_rslog
한 줄을 줄일 수 있습니다/var/log/rsycn.log
.한 줄이 너무 길어서 함수 코드의 가독성이 저하되었다고 생각되면 여러 줄로 나눌 수 있습니다.
\
마지막 줄을 제외한 모든 줄에 하나를 추가합니다.rsync -av --delete -R "$1" "$2" "$3" | grep -E \ '^deleting|[^/]$' >> /var/log/rsync.log
|
특별한 경우로,&&
직후에 중단하는||
경우\
선택 사항입니다 . 또는:rsync -av --delete -R "$1" "$2" "$3" | grep -E '^deleting|[^/]$' >> /var/log/rsync.log
위에서 언급했듯이 이 함수는 항상 세 개의 인수로 호출된다고 가정합니다. 이 가정은 비현실적인 것 같습니다. 명령을 실행
rsync
하고 모든 인수를 함수에 전달하려면 다음을 사용하십시오"$@"
.rsync -av --delete -R "$@" | grep …
grep
예를 들어, 인수를 인수로 사용하도록 함수를 변경하려는 경우my_rsync_grep --exclude=대안 /etc/ /backup.raw/(다른 매개변수)'^삭제|[^/]$'
다음을 수행할 수 있습니다.
my_rsync_grep() { nargs=$(($#-1)) rsync -av --delete -R "${@:1:nargs}" | grep -E "${@:$#}" >> /var/log/rsync.log }
보다매개변수 확장부분큰 타격(1)
$@
및 와 같은 구문에 대한 추가 정보.${parameter:offset:length}
참고: 이 구문은 에서 작동하지 않을 수 있습니다
bash
.