在shell脚本中使用Perl单行程序

时间:2015-08-20 09:24:48

标签: bash perl shell debian

这让我几个小时感到沮丧。我在Perl one-liner周围编写了一个简单的包装器来更新某些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

我尝试了多种不同的方式,但是它无声地或使用消息

失败
  

无法找到字符串终结符"'" EOF之前的任何地方-e line 1 ..

如果我执行echoed命令,它可以完美地运行

我正在使用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

2 个答案:

答案 0 :(得分:2)

至少有一个引用问题。您将单引号作为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

答案 1 :(得分:0)

正确引用应该有所帮助。您还没有显示输入数据,所以我无法测试:

saCMD="s/^(\W*)\d*.*;\W*serial/\${1}$SERIAL ; serial/g" # No inner quotes.
perl -pi -e "$saCMD" "$name"

此外,/g似乎毫无意义,因为正则表达式只匹配字符串的开头(^)。