【问题标题】:Execute Perl Script from Bash script从 Bash 脚本执行 Perl 脚本
【发布时间】:2016-08-26 11:45:00
【问题描述】:

好的,所以我有以下脚本可以从 url 列表 (urls.txt) 中抓取联系人详细信息。当我直接从终端运行以下命令时,我得到了正确的结果

perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' http://url.com 

但是,当我从脚本中调用上述命令时,我得到“没有这样的文件或目录”的结果

这是我的脚本的副本

#!/bin/bash

while read inputline
do
  //Read the url from urls.txt
  url="$(echo $inputline)"

  //execute saxon-lint to grab the contents of the XPATH from the url within urls.txt
  mydata=$("perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' $url ")

  //output the result in myfile.csv
  echo "$url,$mydata" >> myfile.csv

  //wait 4 seconds
  sleep 4

//move to the next url
done <urls.txt

我尝试将 perl 更改为 ./ 但得到相同的结果

谁能告诉我这哪里出了问题

我收到的错误是

./script2.pl: line 6: ./saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' http://find.icaew.com/listings/view/listing_id/20669/avonhurst-chartered-accountants : No such file or directory

提前致谢

【问题讨论】:

  • 尝试使用绝对路径。
  • 试过但结果相同
  • 使用\ to escape the /
  • 标题中声称的 perl 中的这个 perl 如何?这是 bash 中的 perl。
  • 我是 linux 新手,所以你必须原谅使用的术语

标签: linux bash perl


【解决方案1】:

不要在命令替换中添加双引号。

不是:

mydata=$("perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' $url ")
# .......^...........................................................................................^

但是这个:

mydata=$(perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' $url )

使用双引号,您是在指示 bash 在路径、空格和所有内容中查找名为“perl saxon-lint.pl --html etc etc”的程序,显然不存在这样的程序。

【讨论】:

  • 您可能打算将引号放在命令替换之外,但对于变量赋值,它们并不是绝对必要的。
【解决方案2】:

您应该接受@glennjackman 的回答,因为这正是问题所在。这一行:

mydata=$("perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' $url ")

告诉shell运行这个命令:

"perl saxon-lint.pl --html --xpath 'string-join(//div[2]/div[2]/div[1]/div[2]/div[2])' $url "

... 包括双引号。如果你在 shell 提示符下用双引号输入,你会得到与你从脚本中得到的相同的“没有这样的文件或目录”错误消息。

关于脚本的其他几点说明:

  url="$(echo $inputline)"

这是将第二个变量复制为第一个变量的一种迂回方式。一个简单的url=$intputline 也可以,但您也可以首先使用read url。不知道为什么需要两个变量。

  //output the result in myfile.csv
  echo "$url,$mydata" >> myfile.csv

请注意,将包含用户提供的输入的变量作为第一个参数传递给echo 时,您可能会产生意外行为。在这种情况下,这种可能性很小,因为 URL 不太可能以 - 字符开头,但最好改掉这个习惯;我会使用printf。另外,我不会在循环中附加每一行,而是将循环的输出与输入一起重定向:

  printf '%s,%s\n' "$url" "$mydata"
  [...]
done <urls.txt >>myfile.csv

如果您不希望 myfile.csv 存在或有任何需要保留在循环顶部的内容,您可以将其更改为单个 &gt; 并避免来自不同运行的输出混乱混合的可能性.

【讨论】:

  • 是的,包括它们.. 尝试在命令行中输入带有引号的"ls",您将获得一个目录列表。 shell 不区分单词和字符串。所有引号都可以让您不必转义字符(包括空格)。对于 shell,"ls"ls(以及 'ls'\lsl\s\l\s...)完全相同(除了引用的版本不会触发别名查找) .如果你尝试"ls -l",那么你会得到一个错误,因为它正在寻找一个名为ls -l 的命令,而不是寻找一个名为ls 的命令并使用-l 的参数运行它。