Bash 编程 (Cygwin):非法字符 ^M
我的性格有问题。我认为这是dos和unix之间的转换问题。
我有一个浮点值变量。 当我使用 echo 命令打印它时,我得到:
0.495959
但是当我尝试使用 bc 命令对该值进行操作时(我不知道如何编写 bc 命令)。
echo $mean *1000 |bc
我得到:
(standard_in) 1 : illegal character: ^M
我已经在我的 .sh 文件上使用了 dos2unix 命令。 我认为这是因为我的变量有 ^M 字符(不是用 echo 命令打印的)
我怎样才能消除这个错误?
I have a problem with a character. I think it's a conversion problem between dos and unix.
I have a variable that is a float value.
When I print it with the echo command i get:
0.495959
But when I try to make an operation on that value with the bc command (I am not sure how to write the bc command).
echo $mean *1000 |bc
I get:
(standard_in) 1 : illegal character: ^M
I already use the dos2unix command on my .sh file.
I think it's because my variable have the ^M character (not printed with the echo command)
How can i eliminate this error?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我手边没有 Cygwin,但在常规 Bash 中,您可以使用 tr -d 命令来删除指定字符,并且可以使用 $'...' 表示法在命令行参数中指定奇怪的字符(它就像普通的单引号字符串,只是它支持 C/Java/Perl/等类似的转义序列)。因此,这
它将修改
$mean
以去掉其中的任何回车符,然后您就不必在以后使用它的命令中担心它。(不过,也值得看一下设置
\r' | bc$mean
开头的代码。无论如何,$mean
最终如何在其中包含回车符?也许你可以解决这个问题。)将删除从
echo
到bc
途中的回车符。您实际上可能想运行此命令:
它将修改
$mean
以去掉其中的任何回车符,然后您就不必在以后使用它的命令中担心它。(不过,也值得看一下设置
$mean
开头的代码。无论如何,$mean
最终如何在其中包含回车符?也许你可以解决这个问题。)I don't have Cygwin handy, but in regular Bash, you can use the
tr -d
command to strip out specified characters, and you can use the$'...'
notation to specify weird characters in a command-line argument (it's like a normal single-quoted string, except that it supports C/Java/Perl/etc.-like escape sequences). So, this:which will modify
$mean
to strip out any carriage-returns inside, and then you won't have to worry about it in later commands that use it.(Though it's also worth taking a look at the code that sets
\r' | bc$mean
to begin with. How does$mean
end up having a carriage-return in it, anyway? Maybe you can fix that.)will strip out carriage-returns on the way from
echo
tobc
.You might actually want to run this:
which will modify
$mean
to strip out any carriage-returns inside, and then you won't have to worry about it in later commands that use it.(Though it's also worth taking a look at the code that sets
$mean
to begin with. How does$mean
end up having a carriage-return in it, anyway? Maybe you can fix that.)这有效:
您可以通过依次键入 Ctrl-V 和 Ctrl-M 来获取 ^M。或者,另一种选择:
与 @ruakh 相比,此方法的好处是这里仅使用 bash 内置函数。第一个会更快,因为第二个将在子 shell 内运行。
如果你只是想“unixize”$mean:
编辑:还有另一种方法:
This works:
You can get ^M by typing Ctrl-V followed by Ctrl-M. Or, alternatively:
The benefit of this method compared to @ruakh's is that here you are using bash built-ins only. The first will be faster as the second will run inside a subshell.
If you just want to "unixize" $mean:
Edit: There's yet another way:
正如您所发现的,在 cygwin 中运行 Windows 东西有一个令人讨厌的副作用 - 在 cygwin bash 变量中捕获 Windows 程序的输出也会捕获程序的 CR 输出。
明智地使用 d2u 可以避免这个问题 - 例如,
(如果没有 d2u,${runtime} 将在末尾添加一个 CR,这会导致您在将其输入到“bc”时遇到的问题。)
Running Windows stuff in cygwin has one nasty side-effect as you found out - capturing the output of Windows programs in a cygwin bash variable will also capture the CR output by the program.
Judicious use of d2u avoids the issue - for example,
(Without the d2u, ${runtime} would have a CR tacked on the end, which causes the problem you saw when you feed it to 'bc' for example.)
也许您应该将脚本保存为 UNIX 格式而不是 DOS 格式。
Maybe you should just save your script in UNIX format instead of DOS.
试试这个:
如果 echo 确实没有打印它,它应该可以工作。
Try this:
If echo really isn't printing it, it should work.
^M
是一个 回车 字符,在 Windows 中与换行符 (\n
) 表示下一行。然而,这不是 UNIX 世界中的做法,因此bash
不会将 at 视为特殊字符,并且会破坏语法。您需要做的是使用多种方法之一删除该字符。例如,dos2unix
工具可以派上用场。^M
is a carriage return character that is used in Windows along with newline (\n
) character to indicate next line. However, it is not how it is done in UNIX world, and sobash
doesn't treat at as a special character and it breaks the syntax. What you need to do is to remove that character using one of many methods.dos2unix
tool can come handy, for example.正如其他人指出的那样,这是 Windows 行结束问题。有很多方法可以解决这个问题,但问题是为什么会发生这种情况。
我可以在几个地方看到这种情况发生:
这是 Cygwin 启动时设置的 WINDOWS 环境变量。有时这些变量的末尾会有一个 CRLF。您提到这是该变量的一个特殊问题,但您没有指定它的设置位置。
您使用 Windows 文本编辑器(例如 Notepad 或 Winpad)编辑此文件。
切勿使用文本编辑器来编辑程序。使用程序编辑器。如果您喜欢 VI,请下载 VIM,它可在 Windows 上使用,并可在 Cygwin(以及所有其他基于 Unix 的平台)上使用。如果 VIM 不适合您,请尝试更加基于图形的 Notepad++。这两个编辑器都可以处理行尾问题,并且可以在 Windows 中创建具有 Unix 行结束符的脚本,或在 Cygwin 中创建具有 Windows 行结束符的文件。
如果您使用 VIM,您可以执行以下操作来更改行结尾并进行设置:
:set ff?
。:set ff=unix
。:set ff=dos
。如果您使用Notepad++
Mac
作为选项。这甚至在 Mac 上都不起作用。如果您使用的是 Mac,请选择Unix
。As others have pointed out, this is a Windows line ending issue. There are many ways to fix the problem, but the question is why did this happen in the first place.
I can see this happening in several places:
This is a WINDOWS environment variable that was set when Cygwin started up. Sometimes these variables get a CRLF on the end of them. You mentioned this was a particular issue with this one variable, but you didn't specify where it was set.
You edited this file using a Windows text editor like Notepad or Winpad.
Never use a text editor to edit a program. Use a program editor. If you like VI, download VIM which is available on Windows and comes on Cygwin (and all other Unix-based platforms). If VIM isn't for you, try the more graphically based Notepad++. Both of these editors handle end of line issues, and can create scripts with Unix line endings in Windows or files with Windows line endings in Cygwin.
If you use VIM, you can do the following to change line endings and to set them:
:set ff?
while in command mode.:set ff=unix
while in command mode.:set ff=dos
while in command mode.If you use Notepad++
Mac
as an option. That doesn't even work on Macs. If you have a Mac, selectUnix
.