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是这样做的:
- 它解析命令并查看
IFS=something
和 sorted=something
,将它们标记为变量赋值,将它们从命令行中取出
- 然后发现没有其他东西可以作为命令执行,
- 然后,从左到右,分配当前shell中的那些变量
- IFS 设置为
$'\r\n
- 在处理已排序的分配时,bash 执行其扩展:
- 执行命令替换:
"${array[*]}"
扩展为字符串 a c\rb\rf\r3 5
因为 [*]
参数扩展使用 $IFS 的 第一个字符 连接数组元素.
sort -r <<<$'a c\rb\rf\r3 5'
,因为给了一行输入,returns输入不变。
- 现在我们有
sorted=($'a c\rb\rf\r3 5')
,由于命令替换未加引号,因此发生分词:使用 IFS 的字符作为分隔符拆分字符串
- 所以我们最终得到
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
中搜索等效选项。
- 正常排序并使用另一个命令反转排序的输出,例如
tac
(cat
的反转),或者如果它不可用 perl -e 'print reverse <>'
.
示例: 而不是 sort -r <<< "string"
使用 sort <<< "string" | tac
.
另请查看 了解脚本中可能存在的问题。
在 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是这样做的:
- 它解析命令并查看
IFS=something
和sorted=something
,将它们标记为变量赋值,将它们从命令行中取出 - 然后发现没有其他东西可以作为命令执行,
- 然后,从左到右,分配当前shell中的那些变量
- IFS 设置为
$'\r\n
- 在处理已排序的分配时,bash 执行其扩展:
- 执行命令替换:
"${array[*]}"
扩展为字符串a c\rb\rf\r3 5
因为[*]
参数扩展使用 $IFS 的 第一个字符 连接数组元素.sort -r <<<$'a c\rb\rf\r3 5'
,因为给了一行输入,returns输入不变。
- 现在我们有
sorted=($'a c\rb\rf\r3 5')
,由于命令替换未加引号,因此发生分词:使用 IFS 的字符作为分隔符拆分字符串 - 所以我们最终得到
sorted=("a c" b f "3 5")
,它恰好与原始数组具有相同的顺序。
- IFS 设置为
我对你脚本行尾的评论:
当 脚本文件 具有 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
中搜索等效选项。 - 正常排序并使用另一个命令反转排序的输出,例如
tac
(cat
的反转),或者如果它不可用perl -e 'print reverse <>'
.
示例: 而不是sort -r <<< "string"
使用sort <<< "string" | tac
.
另请查看