Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在Bash、test和双括号语法中比较字符串的字母顺序_Linux_Bash_Unix_String Comparison - Fatal编程技术网

Linux 在Bash、test和双括号语法中比较字符串的字母顺序

Linux 在Bash、test和双括号语法中比较字符串的字母顺序,linux,bash,unix,string-comparison,Linux,Bash,Unix,String Comparison,我正在从事一个Bash脚本项目,在该项目中,如果两个文件的内容相同,我需要删除其中一个文件。我应该删除按字母顺序排在最后的一个,在我的教授提供的示例输出中,当选择为apple.dat和apple.dat时,apple.dat被删除 if [[ "apple" > "Apple" ]]; then echo apple else echo Apple fi 打印苹果 echo $(echo -e "Apple\napple&

我正在从事一个Bash脚本项目,在该项目中,如果两个文件的内容相同,我需要删除其中一个文件。我应该删除按字母顺序排在最后的一个,在我的教授提供的示例输出中,当选择为apple.dat和apple.dat时,apple.dat被删除

if [[ "apple" > "Apple" ]]; then
    echo apple
else
    echo Apple
fi
打印苹果

echo $(echo -e "Apple\napple" | sort | tail -n1)
打印苹果

echo $(echo -e "Apple\napple" | sort | tail -n1)
a的ASCII值是97,a是65,为什么测试说a更大

奇怪的是,我得到了与旧语法相反的结果:

if [ "apple" \> "Apple" ]; then
    echo apple
else
    echo Apple
fi
打印苹果

如果我们尝试在[[]]语法中使用\>则是语法错误

我们如何纠正双括号语法的错误?我已经在学校的Debian服务器、本地机器和数字海洋水滴服务器上进行了测试。在我本地的Ubuntu 20.04和学校服务器上,我得到了上述输出。有趣的是,我的Digital Ocean droplet是一台Ubuntu 20.04服务器,我得到了双括号和单括号语法的“apple”。我们可以使用语法、双括号或单括号实际测试调用,但是我更喜欢使用较新的双括号语法,并且更愿意学习如何实现这一点,而不是将我大部分完成的脚本转换为较旧的更符合POSIX的语法。

提示:

$ (LC_COLLATE=C; if [ "apple" \> "Apple" ]; then echo apple; else echo Apple; fi)
apple
$ (LC_COLLATE=en_US; if [ "apple" \> "Apple" ]; then echo apple; else echo Apple; fi)
apple
但是:

区别在于特定于Bash的测试
[[]]
使用区域设置排序规则来比较字符串。而POSIX测试
[]
使用ASCII值

从bash手册页:

当与
[[
一起使用时,
运算符使用当前区域设置按字典排序

当与
test
[
一起使用时,
运算符使用ASCII排序进行字典排序


更改语法。
如果[[“Apple”-gt“Apple”]]
按预期工作。

我已经想出了我自己的解决方案,但是我必须首先感谢@Gordondavison和@LéaGris的帮助以及我从他们那里学到的东西,因为这对我来说是非常宝贵的

无论使用计算机还是人类语言环境,如果按照字母顺序,苹果在苹果之后,那么它也在香蕉之后,如果香蕉在苹果之后,那么苹果在苹果之后。因此,我得出以下结论:

# A function which sorts two words alphabetically with lower case coming after upper case.
# The last word in the sort will be printed twice to demonstrate that this works for both
# the POSIX compliant single bracket test call and the newer double bracket condition
# syntax.
# arg 1: One of two words to sort
# arg 2: One of two words to sort
# Return: 0 upon completion, 1 if incorrect number of args is given
sort_alphabetically() {
    [ $# -ne 2 ] && return 1

    word_1_val=0
    word_2_val=0

    while read -n1 letter; do
        (( word_1_val += $(printf '%d' "'$letter") ))
    done < <(echo -n "$1")

    while read -n1 letter; do
        (( word_2_val += $(printf '%d' "'$letter") ))
    done < <(echo -n "$2")

    if [ $word_1_val -gt $word_2_val ]; then
        echo $1
    else
        echo $2
    fi

    if [[ $word_1_val -gt $word_2_val ]]; then
        echo $1
    else
        echo $2
    fi

    return 0
}

sort_alphabetically "apple" "Apple"
sort_alphabetically "Banana" "apple"
sort_alphabetically "aPPle" "applE"
这使用进程替换和重定向输出到while循环中,一次读取一个字符,然后使用printf获取每个字符的十进制ASCII值。这就像从自动销毁的字符串创建一个临时文件,然后一次读取一个字符。表示echo的-n表示如果有来自用户输入或其他内容的字符,\n将被忽略

从bash手册页:

过程替换


进程替换允许使用文件名引用进程的输入或输出。它采用
(列表)
的形式。进程列表以异步方式运行,其输入或输出显示为文件名。此文件名作为扩展结果作为参数传递给当前命令。如果
(列表)
使用表单,写入文件将为列表提供输入。如果
您使用的是什么语言环境(在您的计算机、学校Debian服务器和DO droplet上)?您可以使用
locale
命令找到答案。本地计算机和学校服务器使用的是en_US.UTF-8,正如我预期的,而我的droplet使用的是C.UFT-8.Ah,正如我在这里读到的:这使得按字母顺序排序有所不同shell和环境变量是进程的本地变量(尽管子进程继承了环境变量)。由于脚本作为子进程运行,在脚本中更改
LANG
不会影响父shell。除非您需要在脚本中稍后重置它,否则不要担心重置它。我会添加您自己的答案(或接受Léa),因为我不知道您确定的完整解决方案(我只是提供了一些找到它的指针).我认为变量的局部性是一个恰当的注释。谢谢,这比使用LANG更简洁:)谢谢!在发布问题之前,我在手册页上搜索了字母顺序,没有发现任何有用的内容。应该搜索字典顺序:)非常感谢你们两位Gordon Davison和@Lé谢谢你的帮助。哦,我的印象是,-gt,-eq类型的运算符只用于数值比较。在这种情况下,仅仅因为将字符串作为整数进行比较会得到所需的结果并不意味着它“按预期工作”…这是一个意外。
apple
apple
Banana
Banana
applE
applE