Bash中的字符串比较优先级

时间:2010-09-20 21:26:53

标签: bash compare operator-precedence

以下示例将目录中的所有文件与输入字符串($ string)进行比较并返回匹配的文件名。它不是一种非常优雅和有效的方法来实现这一目标。出于速度目的,我将for条件修改为仅与以$ string的第一个单词开头的文件进行比较。

此脚本出现问题 - 目录中有两个文件:

Foo Bar.txt
Foo Bar Foo.txt

我将它们与字符串"Foo Bar 09.20.2010"进行比较。这将返回该目录中的两个文件,因为两个文件都匹配。但我需要以最精确的方式返回与字符串匹配的文件 - 在我们的示例中,它应该是Foo Bar.txt

此外,如果你有更好的想法如何解决这个问题,请发表你的想法,因为我还没有那么精通脚本,我相信有更好的,甚至更简单的方法。

#!/bin/bash
string="Foo Bar 09.20.2010"

for file in /path/to/directory/$(echo "$string" | awk '{print $1}')*; do

    filename="${file##*/}"
    filename="${filename%.*}"


    if [[ $(echo "$string" | grep -i "^$filename") ]]; then
        result="$file"
        echo $result    
    fi

done

这是我想要实现的细分。目录中的两个文件与两个字符串匹配,括号中的正确/不正确表示结果是否符合我的预期/想要。

目录中的2个文件(剥离扩展以进行匹配):

Foo Bar.txt
Foo Bar Foo.txt

与2个字符串进行比较:

Foo Bar Random Additional Text
Foo Bar Foo Random Additional Text

结果:

compare "Foo Bar"(.txt) against Foo Bar Random Additional Text -> Match (Correct)
compare "Foo Bar"(.txt) against Foo Bar Foo Random Additional Text -> Match (Incorrect)

compare "Foo Bar Foo"(.txt) against Foo Bar Random Additional Text -> NOT Match (Correct)
compare "Foo Bar Foo"(.txt) against Foo Bar Foo Random Additional Text -> Match (Correct)

谢谢大家的回答。

2 个答案:

答案 0 :(得分:1)

如果我错了,请纠正我,但看起来你的脚本相当于:

ls /path/to/directory/"$string"*

如果您只想要一个文件名,则可以使用head。由于ls按字母顺序列出文件,因此您将按字母顺序排列第一个文件。

(请注意,当ls的输出通过管道传输到另一个程序时,它会在每行打印一个文件名,这使得它比正常的基于列的输出更容易处理。)

ls /path/to/directory/"$string"* | head -1

对于最短匹配,请尝试以下内容,它使用awksort -ncut的笨拙组合来排序最短的行最长,然后打印第一个。

ls /path/to/directory/"$string"* |
    awk '{print length($0) "\t" $0}' | sort -n | head -1 | cut -f 2-

答案 1 :(得分:0)

您的echoawk电话很多都是多余的。要获得以匹配开头的所有文件,您只需评估“$ string”*即可。

e.g。两个

echo "$string"*

ls "$string"*

将生成您的列表。 (在管道中,echo将使它们以空格分隔,并且ls将使它们以换行符分隔。)

下一步是要意识到,鉴于此,正如您所定义的那样,“最精确匹配”的额外约束等同于最短的匹配文件名。

要在bash中找到一组字符串中的最短字符串(我自己更喜欢perl,但让我们坚持在bash中执行它的约束):

for fn in "/path/to/$string"*; do
  echo $(echo $fn | wc -c) "$fn"
done | sort -n | head -1 | cut -f2- -d' '

for循环遍历扩展的文件名。 echo将名称的长度添加到名称之前。然后我们将其整个输出管道输入sort -nhead -1以获得最短的名称,并cut -f2- -d' '去除它的长度(将第二个字段用空格作为字段分离器)。

shell编程的关键是了解你的构建块,以及如何组合它们。通过巧妙的排序,头部,尾部和切割组合,您可以进行许多非常复杂的处理。扔进sed和uniq,你已经能够做一些非常令人印象深刻的事情了。

话虽这么说,我通常只使用shell来实现这样的“动态” - 对于我可能想要重复使用的任何东西,这一切都很复杂我会更有可能使用的Perl。