Bash逐行传参至Perl脚本时正则匹配失效问题求助
嘿,我懂你遇到的这个头疼问题——把整个配置文件内容一次性传给Perl时正则能正常匹配,但用Bash逐行传参就完全拿不到结果,这其实是Bash的参数拆分机制在捣乱!
问题根源在哪?
你看,当Bash执行perl /mnt/c/LINUX_STUFF/regex.pl $line时,它会把$line里的空格当成参数分隔符,把一行内容拆成好几个独立参数传给Perl。比如配置文件里的ORACLE_BASE = /u01/oracle这行,Perl拿到的$ARGV[0]只有ORACLE_BASE,剩下的=和/u01/oracle分别变成了$ARGV[1]和$ARGV[2]。而你的Perl代码只检查$ARGV[0],自然匹配不到符合(^\S*) = (\S*)格式的内容啦!
两种快速解决办法
办法1:给Bash变量加引号,保住整行内容
最简单的修复就是在传参时把$line用双引号包裹,这样Bash就会把整行当成一个完整参数传给Perl:
while IFS= read -r line do RESULT=$(perl /mnt/c/LINUX_STUFF/regex.pl "$line") echo $RESULT done < example.config
加了双引号后,Perl的$ARGV[0]就能拿到完整的一行内容,你的正则就能正常工作了。
办法2:让Perl直接读文件,效率更高
其实没必要让Bash做逐行读取的工作,Perl本身就很擅长处理文件。修改你的Perl脚本,让它直接处理文件内容:
use strict; # 读取输入的每一行(支持直接读文件或管道输入) while (my $str = <>) { chomp $str; # 去掉末尾的换行符 my $regex = qr/(^\S*) = (\S*)/mp; if ($str =~ /$regex/) { print "$2\n"; } }
然后Bash脚本可以简化成一行:
perl /mnt/c/LINUX_STUFF/regex.pl example.config
这样不仅避免了传参的坑,还减少了Bash和Perl之间的频繁调用,运行效率会更高。
额外小提示
你的正则(^\S*) = (\S*)只能匹配值部分没有空格的配置项,如果以后遇到值带空格的情况(比如APP_NAME = My Oracle App),这个正则就会失效。可以把正则调整成(^\S*) = (.*),这样就能匹配等号后面的所有内容啦。
内容的提问来源于stack exchange,提问作者LifeLifeLP

