pie*_*e_j 3 bash regular-expression for
我有一个 bash 脚本,可以从远程服务器分类和检索文件。我对基于文件名的分类步骤有问题。
我能够正确识别由文件名开头定义的不同文件系列。文件名可以是:
ala-olo_ulu-1602915797.txt
ala-olo_ulu-1602915799.txt
ili-olo-1602915897.txt
ili-olo-1602915997.txt
ili-olo-pip-1602925797.txt
ili-olo-pip-1602935797.txt
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我有 3 个家庭:(
ala-olo_ulu
ili-olo
ili-olo-pip
纯例子:))
每个系列都在循环的一次迭代中进行处理。在这样的迭代中,我在变量中提供了姓氏BASE_NAME(例如ili-olo)。
我的麻烦是在将文件同步到本地之前的去皮步骤。我正在使用以下 ssh 命令管理它。
ssh root@"${RMT_IP}" '
for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do
tar -rf "'${BASE_NAME}'.tar" ${FILE} --remove-files
done' < /dev/null
Run Code Online (Sandbox Code Playgroud)
不幸的是,使用此脚本,如果ili-olo在之前管理ili-olo-pip,则存档将包含两个系列(它们共享相同的开始)。然后什么时候ili-olo-pip进行管理,它们将不再是任何文件,并且 tar 命令以错误结束。(这就是我发现问题的方式)。
我想,我应该使用正则表达式来指定文件名的可变部分是数字部分。请问,如何更改for循环定义,以便以相同字符串开头的系列不会进入相同的 tar?
for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do
?
数字部分始终具有相同的位数(它是一个时间戳,具有第二个精度),例如 1602915797
我感谢你的帮助。祝你有美好的一天,贝斯特斯,皮埃尔
如果您可以zsh同时用作本地和远程 shell,则更容易:
ssh root@$RMT_IP zsh << EOF
set -o extendedglob # for (#c10)
for file in ${(qq)BASE_NAME}-[0-9](#c10).${(qq)FILE_EXTENSION}(N); do
tar -rf ${(qq)BASE_NAME}.tar \$file --remove-files
done
EOF
Run Code Online (Sandbox Code Playgroud)
[0-9](#c10)匹配 10 个十进制数字的序列。对于组成该范围内的数字的十进制数字序列,另请参阅[0-9]##与[0-9](#c1,)一位或多位数字相同的内容或<100000-9999999999>(不需要extendedglob)。
sshd在服务器上运行用户的登录 shell 来解释作为参数传递的代码。由于我们不知道它是什么(通常用于root,那只是sh),我们只是制作该代码zsh,以启动zshshell 并zsh在标准输入上传递代码。
使用像这样的 here-document 可以更容易地构造要由那里的远程 shell 解释的 shell 代码。由于EOF没有引用,本地 shell 将在本地执行扩展。
跟踪哪些扩展是在本地完成的,哪些是由远程 shell 完成的,这一点很重要。
上面${(qq)BASE_NAME}是本地shell展开的,我们使用(qq)参数展开标志将结果用单引号括起来,这样远程shell就把它当成文字串了。
$file必须由远程 shell 扩展,因此我们将其添加为前缀,\以便将文字$file传递给远程 shell。
如果zsh在远程机器上不可用,但是bash,您可以这样做(仍在zsh本地使用):
ssh root@$RMT_IP bash --norc << EOF
shopt -s extglob nullglob # for +(...)
export LC_ALL=C
for file in ${(qq)BASE_NAME}-+([0-9]).${(qq)FILE_EXTENSION}; do
tar -rf ${(qq)BASE_NAME}.tar "\$file" --remove-files
done
EOF
Run Code Online (Sandbox Code Playgroud)
bash没有相当于zsh的x(#c10)glob 运算符,但是使用extglob,它支持 ksh 的一个子集({10}(x)虽然不幸在这里不是),包括+(x)匹配一个或多个x. 所以这+([0-9])将匹配一位或多位数字,而不仅仅是 10。
要匹配 10 位数字,您仍然可以执行[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].