为什么我的 Bash 脚本没有返回这个欧拉项目的正确答案?

为什么我的 Bash 脚本没有返回这个欧拉项目的正确答案?

我正在尝试使用 Bash 来完成欧拉计划 13。下面是我的代码,我就是不知道它哪里出了问题。

#!/bin/bash                                                
sum=0                                                      
while read -r -d $'\r' line; do                            
    sum=$(echo $sum + $line | bc)                          
done <<< "$(curl -s http://pastebin.com/raw/uHZ0PZjm)"     
echo "${sum:0:10}"                                         
exit 

                             

它曾经导致两个错误,

(standard_in) 1: syntax error

(standard_in) 1: illegal character: ^M

经过一番研究,这似乎是 EOF 终止符的问题。然后我在其上运行了 dos2unix,它不再给出第二个错误,但仍然重复给出第一个错误。这似乎是我将数据导入 bc 的方式存在一些问题,但我不知道该做什么或如何修复它。

正确答案是 5537376230。非常感谢您提供的任何帮助!

系统信息是

GNU bash,版本 4.3.11(1)-发布(x86_64-pc-linux-gnu)

我在 Windows 10 上使用 cmder。

答案1

您需要将 \n ( == 0x0a == LF == 换行符) 设置为read分隔符,而不是\r( == 0x0d == CR == 回车符)。要么这样,要么确保在 pastebin 文件末尾放置一个 CR。看起来您的 pastebin 文件在最后一行的末尾缺少行终止符序列,因此最后一行永远不会被输入到您的脚本中。

$ curl -s http://pastebin.com/raw/uHZ0PZjm | hexdump -C | tail -n 8
...(snip)...
000013e0  35 30 39 35 31 36 0d 0a  32 30 38 34 39 36 30 33  |509516..20849603|
000013f0  39 38 30 31 33 34 30 30  31 37 32 33 39 33 30 36  |9801340017239306|
00001400  37 31 36 36 36 38 32 33  35 35 35 32 34 35 32 35  |7166682355524525|
00001410  32 38 30 34 36 30 39 37  32 32 0d 0a 35 33 35 30  |2804609722..5350|
00001420  33 35 33 34 32 32 36 34  37 32 35 32 34 32 35 30  |3534226472524250|
00001430  38 37 34 30 35 34 30 37  35 35 39 31 37 38 39 37  |8740540755917897|
00001440  38 31 32 36 34 33 33 30  33 33 31 36 39 30        |81264330331690|
0000144e

请注意,每个数字之间都有一个 0x0d0a(CR LF),但最后一个数字之后没有。

$ while read -r -d $'\r' line; do echo $line; done <<< "$(curl -s http://pastebin.com/raw/uHZ0PZjm)" | tail -n 3
77158542502016545090413245809786882778948721859617
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722

请注意,在运行命令时,最后一个数字 535[...]690 会丢失read。但如果您将分隔符切换为 Unix 原生的 LF (\n) 换行符,则会包含最后一行:

$ while read -r -d $'\n' line; do echo $line; done <<< "$(curl -s http://pastebin.com/raw/uHZ0PZjm)" | tail -n 3
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722
53503534226472524250874054075591789781264330331690

编辑后添加:以下是处理 pastebin 文件中 CR 的修复方法。我告诉read使用 CRLF 作为分隔符,并使用额外的 echo 在 pastebin 文件后添加 CRLF。

sum=0
while read -r -d $'\r\n' line; do
    sum=$(echo $sum + $line | bc)
done <<< $(curl -s http://pastebin.com/raw/uHZ0PZjm; echo -e "\r\n")
echo "${sum:0:10}"

答案2

你可以这样做:

mapfile -t lines < <(curl -s http://pastebin.com/raw/uHZ0PZjm | sed 's/\r$//')
sum=0
for bignum in "${lines[@]}"; do 
    sum=$(bc <<< "$sum + $bignum")
done
echo "${sum:0:10}"    # ==> 5537376230

使用:

  • A流程替代包含对 curl 的调用并通过管道传输到 sed 以删除回车符。
  • 重定向到映射文件将输入的行读入 shell 数组
  • 迭代数组并使用传入的表达式调用 bc此处字符串

相关内容