错误:使用-r标志时,“系统找不到指定的文件”

时间:2019-03-06 21:06:08

标签: bash cygwin

在Windows XP上使用cygwin bash。 Bash版本:4.3.46(7)-发布。最小的工作示例,以相反的顺序对数组进行排序:

#!/bin/bash
array=("a c" b f "3 5")
IFS=$'\r\n' sorted=($(sort -r <<<"${array[*]}"))
printf "[%s]\n" "${sorted[@]}"

cygwin中的错误:

-rThe system cannot find the file specified.

在Linux上工作正常。该错误是由-r标志引起的。如何解决?

2 个答案:

答案 0 :(得分:1)

我不认为像这样干扰IFS会给您带来想要的结果。试试这个:

#!/bin/bash
array=("a c" b f "3 5")
readarray -t sorted < <(printf "%s\n" "${array[@]}" | sort -r)
printf "[%s]\n" "${sorted[@]}"

哪个输出

[f]
[b]
[a c]
[3 5]

我认为您的困难就在这里:

IFS=$'\r\n' sorted=($(sort -r <<<"${array[*]}"))

bash引用Simple Command Expansion

  1. 它解析命令并查看IFS=somethingsorted=something,将它们标记为变量分配,将其从命令行中删除
  2. 然后没有其他要执行的命令
  3. 然后从左到右在当前shell中分配这些变量
    1. IFS设置为$'\r\n
    2. 在处理排序后的分配时,bash执行其扩展:
    3. 执行命令替换:
      1. "${array[*]}"扩展为字符串a c\rb\rf\r3 5,因为[*]参数扩展使用$ IFS的第一个字符连接数组元素。
      2. sort -r <<<$'a c\rb\rf\r3 5'由于已获得输入的一行,因此不会更改输入。
    4. 现在我们有了sorted=($'a c\rb\rf\r3 5'),由于未使用命令替换,因此会发生单词拆分:使用IFS字符作为分隔符来拆分字符串
    5. 所以我们最终得到sorted=("a c" b f "3 5"),它恰好具有与原始数组相同的顺序。

我对脚本行尾的评论:

脚本文件具有DOS样式的CRLF行结尾时,bash将第一行视为

array=("a c" b f "3 5")$'\r'

这意味着array不是数组,而是单个值:

$ IFS=$' \t\n'  # the default value
$ array=("a c" b f "3 5")$'\r'
$ declare -p array
"eclare -- array="(a c b f 3 5)
# ......^^ _not_ "-a" !

答案 1 :(得分:1)

似乎您的sort版本不支持-r标志。你可以...

  • man sort中搜索等效选项。
  • 正常排序并使用另一个命令,例如tac(与cat相反)或如果perl -e 'print reverse <>'不可用,则反转排序的输出。
    示例:使用sort -r <<< "string"代替sort <<< "string" | tac

也请查看Glenn Jackman's Answer有关脚本中可能存在的问题。