我正在尝试编写一个bash脚本,以便找到包含特定字符串的文件。该脚本调用另一个返回格式字符串的脚本:
url=title
title
是我要找的字符串。 title
可以包含如下所示的值:'A Soldier Of The Legion'
。
我试图在/tmp/audiobooks
目录中找到包含标题'A Soldier Of The Legion'
的文件。 /tmp/audiobooks
中的所有文件的名称都以AB.yaml
结尾。
这是脚本:
#!/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
脚本产生的输出是:
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命令都有效...例如:
$ 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)'
。
答案 0 :(得分:3)
如果这一行:
echo "grep -l $apptitle /tmp/audiobooks/*AB.yaml | head -1"
生成如下输出:
grep -l 'A Soldier Of The Legion' /tmp/audiobooks/*AB.yaml | head -1
然后,这意味着apptitle
的值包含单引号。
您可以尝试这样做以了解发生了什么:
value1='A Soldier Of The Legion'
value2="'A Soldier Of The Legion'"
echo "$value1"
echo "$value2"
输出:
A Soldier Of The Legion
'A Soldier Of The Legion'
换句话说,脚本真正执行的是:
grep -l "'A Soldier Of The Legion'" /tmp/audiobooks/*AB.yaml | head -1
仅当yaml
文件包含由单引号括起的标题时才会匹配。
您可能想要从apptitle
中删除单引号,例如:
apptitle=$(echo $i | cut -d= -f2- | cut -c1-52 | sed -e "s/^'//" -e "s/'$//")
上面的sed
将在每一端删除单引号,并在字符串的中间留下其他单引号。
答案 1 :(得分:1)
$apptitle
包含标题周围的开始和结束单引号('
)字符,您的脚本会将它们传递给grep
。
grep
。这就是说您的脚本没有运行您希望它运行的grep
命令。.yaml
文件在搜索的标题周围有单引号,则该脚本将适用于这些文件。但它对其他人不起作用。 (我希望这就是它适用于你的一个游戏的原因。)根据您的问题的早期编辑记录,您似乎可能已考虑过这种可能性,并试图通过更改来阻止它
the_file=$(grep -l "$apptitle" /tmp/audiobooks/*AB.yaml | head -1)
改为:
the_file=$(grep -l $apptitle /tmp/audiobooks/*AB.yaml | head -1)
这不会有帮助。 '
仍在那里。 (我建议撤消这种改变,但由于你已经分配了IFS
的价值,这可能没问题。)
当参数展开('
)的结果中出现$apptitle
等引用字符时,shell不会特别对待它。它不会阻止word splitting,也不会受quote removal的限制。
例如,当IFS
具有默认值时,x="'a b c'"; printf '(%s)' $x
的输出为('a)(b)(c')
,而不是(a b c)
。也就是说,当x
保留值'a b c'
时,不带引号的$x
会扩展为'a b c'
,而分词会将其转换为'a
{{1 }} b
。
在您的情况下,您已更改c'
,因此拆分仅发生在换行符和退格键上。 IFS
匹配行,因此您无法在标题中获得换行符。假设标题不包含退格,那么保持grep
不加引号是很好的(尽管可能风格上令人困惑)。但是这并没有删除封闭的$apptitle
个字符。
答案 2 :(得分:0)
我认为在执行.
时需要放置get-pairs.sh
(点)。前面的点意味着将该文件的内容“源”到当前shell中。
for i in `. $get_pairs`