我正在尝试运行这个开源 bash 脚本,但它不起作用,因为它假设我在解析输入时正在运行 linux。实际上,我在 Windows 机器上运行 cygwin。脚本中有一个地方将 $IFS 设置为\n
,这会留下 a ,\r
这会导致错误,因为它无法匹配确切的字符串。
修改我的本地版本的脚本很容易,但是我该如何解决这个问题,以便它可以在任何操作系统上运行?如果我可以运行一些命令来获取换行符,那么我可以将它们分配给 $IFS。
对于一些额外的上下文,处理换行符的代码是这样的:
IFS=\n
# Word splitting is intended here
# shellcheck disable=2046
set -- $(printf '%s\n' "$_response" | jq -r '
.error,
.access_token,
.token_type,
.expires_in,
.refresh_token,
.scope')
IFS=$oifs
[ "$1" = "null" ] && ...
该测试最终将“null\r”与“null”进行比较。
答案1
脚本中有一个地方将
$IFS
[\n
...]
您向我们展示的代码使用IFS=\n
。不幸的是,这不是IFS='\n'
,最终只会设置IFS=n
。所以无论如何代码都需要修复
答案2
另一个可能有效的选项不是确定您的系统使用哪种行结束符,而是关注您的输入文件使用哪种行结束符。
我这样说是因为(以编程方式)更改文件中的行结尾非常容易,无论是在编写文件时还是通过后处理(通过dos2unix
或类似的方式)。
您可以使用该file
命令提供有关文件正在使用的行结尾的一些信息。
tim@chaos:~/tmp$ file lnx.txt
lnx.txt: ASCII text
tim@chaos:~/tmp$ file win.txt
win.txt: ASCII text, with CRLF line terminators
tim@chaos:~/tmp$ dos2unix -n win.txt win2unix.txt
dos2unix: converting file win.txt to file win2unix.txt in Unix format...
tim@chaos:~/tmp$ file win2unix.txt
win2unix.txt: ASCII text
因此,获取输入文件的脚本可以设置为检查不同的行结尾,并即时修改它们,或者它可以简单地获取任何输入文件并通过dos2unix
.
区别只是\r\n
比较\n
。因此,在 shell 脚本中处理输入流可以捕获任何 CRLF 类型的行结尾,而无需进行任何文件转换。
然而,您的 shell 脚本选择逐行读取文件来处理它们,您可以添加一个额外的sed
步骤。
你可以这样做:
IFS=\n
# Word splitting is intended here
# shellcheck disable=2046
set -- $(printf '%s\n' "$_response" | sed -e s'/\r//g' | jq -r '
.error,
.access_token,
.token_type,
.expires_in,
.refresh_token,
.scope')
IFS=$oifs
[ "$1" = "null" ] && ...
如果存在 CRLF,则将删除它们;如果不存在,则不会更改输入行。
通过让脚本自动转换输入上的不同行结尾,文件的行结尾类型实际上并不重要,并且您的脚本将变得更加可移植。或者至少,输入不可知。