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
变量上失败了。我怎样才能写得正确呢?我尝试使用"…"
and '…'
,但没有成功。请注意原来有效的 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
一种包含(恕我直言)其他两个答案的最佳部分的方法是编写一个 shell 函数,该函数包含您想要不变的所有功能,并采用参数指定您希望在不同的情况下有所不同的功能。实例:
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=alternatives /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
.