Error: "The system cannot find the file specified" when using -r flag

Error: "The system cannot find the file specified" when using -r flag

在 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 标志引起的。如何解决?

我不认为像那​​样乱用 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[*]}"))

参考Simple Command Expansion,bash是这样做的:

  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',因为给了一行输入,returns输入不变。
    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" !

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

  • man sort 中搜索等效选项。
  • 正常排序并使用另一个命令反转排序的输出,例如 taccat 的反转),或者如果它不可用 perl -e 'print reverse <>'.
    示例: 而不是 sort -r <<< "string" 使用 sort <<< "string" | tac.

另请查看 了解脚本中可能存在的问题。