首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在我的脚本中,grep命令返回空的结果,但是从命令行工作。

在我的脚本中,grep命令返回空的结果,但是从命令行工作。
EN

Stack Overflow用户
提问于 2017-07-02 03:09:19
回答 3查看 1.3K关注 0票数 3

我正在尝试编写一个bash脚本,该脚本应该找到其中包含特定字符串的文件。脚本调用另一个返回格式字符串的脚本:

代码语言:javascript
复制
url=title

title是我要找的字符串。title可以有如下所示的值,例如:'A Soldier Of The Legion'。我试图在/tmp/audiobooks目录中找到包含标题'A Soldier Of The Legion'的文件。/tmp/audiobooks中的所有文件都有以AB.yaml结尾的名称。

下面是脚本:

代码语言:javascript
复制
#!/bin/sh

get_pairs='/home/me/util/scripts/get-pairs.sh'
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `$get_pairs`
do
        echo "pair $i"
        url=`echo $i | cut -d= -f1`
        apptitle=`echo $i | cut -d= -f2- | cut -c1-52`
        echo "grep -l $apptitle /tmp/audiobooks/*AB.yaml | head -1"
        the_file=$(grep -l $apptitle /tmp/audiobooks/*AB.yaml | head -1)
        echo "the_file=$the_file"
        if [ -z $the_file ]
        then
                echo "No hiera file found for $apptitle ... skipping"
                continue
        fi
        appname=`basename $the_file .yaml`
        echo "url is[$url] and apptitle is [$apptitle] appname is [$appname]"
        exit 0
done
IFS=$SAVEIFS

脚本产生的输出如下:

代码语言:javascript
复制
pair http://www.example.com/product/B06XK9FGYD='A Soldier Of The Legion'
grep -l 'A Soldier Of The Legion' /tmp/audiobooks/*AB.yaml | head -1
the_file=
No hiera file found for 'A Soldier Of The Legion' ... skipping
pair http://www.example.com/product/B01GWQI0OS='Art of War Sun Tzu'
grep -l 'Art of War Sun Tzu' /tmp/audiobooks/*AB.yaml | head -1
the_file=
No hiera file found for 'Art of War Sun Tzu' ... skipping
pair http://www.example.com/product/B0717333MM='Bartleby, the Scrivener (version 2)'
grep -l 'Bartleby, the Scrivener (version 2)' /tmp/audiobooks/*AB.yaml | head -1
the_file=/tmp/audiobooks/BartlebyTheScrivener_AMZAD_AB.yaml
url is[http://www.example.com/product/B0717333MM] and apptitle is ['Bartleby, the Scrivener (version 2)'] appname is [BartlebyTheScrivener_AMZAD_AB]

奇怪的是,当我从命令行运行每个grep命令时,我响应它们的工作.例如:

代码语言:javascript
复制
$ grep -l 'A Soldier Of The Legion' /tmp/audiobooks/*AB.yaml | head -1
/tmp/audiobooks/A_Soldier_of_the_Legion_AB.yaml

该脚本适用于标题'Bartleby, the Scrivener (version 2)'

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-02 04:28:51

如果这一行:

echo "grep -l $apptitle /tmp/audiobooks/*AB.yaml _ head -1“

产生这样的输出:

grep -l‘军团战士’/tmp/有声读物/*AB.yaml_ head -1

这意味着apptitle的值包含单引号。

你可以试试这个来理解发生了什么:

代码语言:javascript
复制
value1='A Soldier Of The Legion'
value2="'A Soldier Of The Legion'"
echo "$value1"
echo "$value2"

产出:

代码语言:javascript
复制
A Soldier Of The Legion
'A Soldier Of The Legion'

换句话说,脚本真正执行的是:

代码语言:javascript
复制
grep -l "'A Soldier Of The Legion'" /tmp/audiobooks/*AB.yaml | head -1

只有当yaml文件包含由单引号包围的标题时,才会匹配。

例如,您可能希望删除apptitle中的单引号:

代码语言:javascript
复制
apptitle=$(echo $i | cut -d= -f2- | cut -c1-52 | sed -e "s/^'//" -e "s/'$//")

上面的sed将去掉两端的单引号,并将其他单引号单独放在字符串的中间。

票数 3
EN

Stack Overflow用户

发布于 2017-07-02 04:29:57

$apptitle包含标题周围的开始和结束单引号(')字符,您的脚本将它们传递给grep

  • 阅读您的脚本,这很容易被忽略,因为您的脚本告诉用户它正在运行--并且您正在手动运行--允许shell执行移除引号,因此不要将这些字符传递给grep。这就是说,您的脚本没有运行您希望它运行的相同的grep命令。
  • 如果您的一些.yaml文件在搜索的标题周围有单引号,脚本将适用于这些文件。但这对其他人不起作用。(我想这就是你的一个头衔的工作机会。)

从您的问题的早期编辑历史来看,您可能已经考虑过这种可能性,并试图通过更改来防止这种可能性。

代码语言:javascript
复制
the_file=$(grep -l "$apptitle" /tmp/audiobooks/*AB.yaml | head -1)

改为:

代码语言:javascript
复制
the_file=$(grep -l $apptitle /tmp/audiobooks/*AB.yaml | head -1)

不会有帮助的。'还在那里。(我建议取消这一更改,但由于您分配了IFS的值,这很可能是可以的。)

当引用字符(如' )出现在参数展开($apptitle)的结果中时,shell不对其进行特殊处理。它不能阻止分词,也不受移除引号的制约。

例如,当IFS有其默认值时,x="'a b c'"; printf '(%s)' $x的输出是('a)(b)(c'),而不是(a b c)。这就是说,当x持有'a b c'值时,未引用的$x扩展为'a b c',而分词将其转化为'a b c'

在您的例子中,您已经更改了IFS,因此拆分只发生在换行符和后置空间上。grep与行匹配,所以标题中不会出现换行符。假设标题永远不包含后置空间,保持$apptitle不被引用是很好的(尽管可能在风格上令人困惑)。但这并不会删除'字符。

票数 1
EN

Stack Overflow用户

发布于 2017-07-02 03:31:16

我认为在执行. ( get-pairs.sh )时需要放置get-pairs.sh(点)。前面的点意味着将该文件的内容“源”到当前的shell中。

代码语言:javascript
复制
for i in `. $get_pairs`
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44867115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档