在 shell 脚本中使用 Perl 单行代码
Using a Perl one-liner in a shell script
这让我沮丧了几个小时。我围绕 Perl 单行编写了一个简单的包装器来更新某些 DNS 区域文件中的序列号。
我觉得有必要补充一点:- 不要提供其他方式来做到这一点,好吗?这是关于为什么这行不通,而不是关于如何通过其他方式达到结果。
这是我的简单脚本
#!/bin/bash
#loop through the supplied files updating the timestamp (serial)
SERIAL=`date +%Y%m%d%H%M`;
for name in $@
do
saCMD="'s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/g'"
#echo the command
echo "perl -pi -e "$saCMD" $name"
#execute the command
`perl -pi -e $saCMD $name`
done
我尝试了多种不同的方法,但都无提示或显示消息失败
Can't find string terminator "'" anywhere before EOF at -e line 1..
如果我执行回显命令,它会正常工作
我使用的是 Debian 7 系统
谁能告诉我为什么这没有像我期望的那样执行?
编辑:
一些示例数据
$TTL 300
domain.org. IN SOA ns1.domain.com. admin.domain.org. (
2014090914 ; serial, todays date+todays
7200 ; refresh, seconds
7200 ; retry, seconds
2419200 ; expire, seconds
3600 ) ; minimum, seconds
感兴趣的行是2014090914 ; serial, todays date+todays
至少有一个引用问题。您将单引号作为 saCMD="'s...'"
的一部分。它们不会被 shell 删除,而是传递给 perl,正如您在 echo
输出中看到的那样。
此外,
#execute the command
`perl -pi -e $saCMD $name`
可能有无用的反引号。或者您还想 运行 perl 脚本输出的命令吗?要调试 shell 脚本,请将 set -x
放在开头。
这在这里有效:
#!/bin/bash
SERIAL=$(date +%Y%m%d%H%M)
for name in "$@"; do
saCMD="s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/"
perl -pi -e "$saCMD" "$name"
done
并将您的示例数据转换为
$TTL 300
domain.org. IN SOA ns1.domain.com. admin.domain.org. (
201508201330 ; serial, todays date+todays
7200 ; refresh, seconds
7200 ; retry, seconds
2419200 ; expire, seconds
3600 ) ; minimum, seconds
适当的引用应该有所帮助。你没有显示输入数据,所以我无法测试:
saCMD="s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/g" # No inner quotes.
perl -pi -e "$saCMD" "$name"
此外,/g
似乎毫无意义,因为正则表达式仅匹配字符串的开头 (^
)。
这让我沮丧了几个小时。我围绕 Perl 单行编写了一个简单的包装器来更新某些 DNS 区域文件中的序列号。
我觉得有必要补充一点:- 不要提供其他方式来做到这一点,好吗?这是关于为什么这行不通,而不是关于如何通过其他方式达到结果。
这是我的简单脚本
#!/bin/bash
#loop through the supplied files updating the timestamp (serial)
SERIAL=`date +%Y%m%d%H%M`;
for name in $@
do
saCMD="'s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/g'"
#echo the command
echo "perl -pi -e "$saCMD" $name"
#execute the command
`perl -pi -e $saCMD $name`
done
我尝试了多种不同的方法,但都无提示或显示消息失败
Can't find string terminator "'" anywhere before EOF at -e line 1..
如果我执行回显命令,它会正常工作
我使用的是 Debian 7 系统
谁能告诉我为什么这没有像我期望的那样执行?
编辑:
一些示例数据
$TTL 300
domain.org. IN SOA ns1.domain.com. admin.domain.org. (
2014090914 ; serial, todays date+todays
7200 ; refresh, seconds
7200 ; retry, seconds
2419200 ; expire, seconds
3600 ) ; minimum, seconds
感兴趣的行是2014090914 ; serial, todays date+todays
至少有一个引用问题。您将单引号作为 saCMD="'s...'"
的一部分。它们不会被 shell 删除,而是传递给 perl,正如您在 echo
输出中看到的那样。
此外,
#execute the command
`perl -pi -e $saCMD $name`
可能有无用的反引号。或者您还想 运行 perl 脚本输出的命令吗?要调试 shell 脚本,请将 set -x
放在开头。
这在这里有效:
#!/bin/bash
SERIAL=$(date +%Y%m%d%H%M)
for name in "$@"; do
saCMD="s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/"
perl -pi -e "$saCMD" "$name"
done
并将您的示例数据转换为
$TTL 300
domain.org. IN SOA ns1.domain.com. admin.domain.org. (
201508201330 ; serial, todays date+todays
7200 ; refresh, seconds
7200 ; retry, seconds
2419200 ; expire, seconds
3600 ) ; minimum, seconds
适当的引用应该有所帮助。你没有显示输入数据,所以我无法测试:
saCMD="s/^(\W*)\d*.*;\W*serial/${1}$SERIAL ; serial/g" # No inner quotes.
perl -pi -e "$saCMD" "$name"
此外,/g
似乎毫无意义,因为正则表达式仅匹配字符串的开头 (^
)。