windows Bash 编程(Cygwin):非法字符 ^M

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8316649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:33:25  来源:igfitidea点击:

Bash programmation (Cygwin): Illegal Character ^M

windowsbashcygwinbc

提问by Frencoo

I have a problem with a character. I think it's a conversion problem between dos and unix.

我的角色有问题。我认为这是dos和unix之间的转换问题。

I have a variable that is a float value. When I print it with the echo command i get:

我有一个浮点值的变量。当我用 echo 命令打印它时,我得到:

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).

但是当我尝试使用 bc 命令对该值进行操作时(我不确定如何编写 bc 命令)。

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)

我已经在我的 .sh 文件中使用了 dos2unix 命令。我认为这是因为我的变量有 ^M 字符(不是用 echo 命令打印的)

How can i eliminate this error?

我怎样才能消除这个错误?

回答by ruakh

I don't have Cygwin handy, but in regular Bash, you can use the tr -dcommand 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:

我手边没有 Cygwin,但在常规 Bash 中,您可以使用该tr -d命令删除指定的字符,并且您可以使用该$'...'符号在命令行参数中指定奇怪的字符(它就像一个普通的单引号字符串,除了它支持 C/Java/Perl/etc.-like 转义序列)。所以这:

echo "$mean" * 1000 | tr -d $'\r' | bc

will strip out carriage-returns on the way from echoto bc.

将在从echoto的途中去除回车符bc

You might actually want to run this:

你可能真的想运行这个:

mean=$(echo "$mean" | tr -d $'\r')

which will modify $meanto strip out any carriage-returns inside, and then you won't have to worry about it in later commands that use it.

这将修改$mean以去除内部的任何回车符,然后您不必在以后使用它的命令中担心它。

(Though it's also worth taking a look at the code that sets $meanto begin with. How does $meanend up having a carriage-return in it, anyway? Maybe you can fix that.)

(虽然它也值得一看设置$mean开始的代码。$mean无论如何,最终如何在其中包含回车?也许你可以解决这个问题。)

回答by pepoluan

This works:

这有效:

${mean/^M/}

${mean/^M/}

You can get ^M by typing Ctrl-V followed by Ctrl-M. Or, alternatively:

您可以通过键入 Ctrl-V 后跟 Ctrl-M 来获得 ^M。或者,或者:

${mean/$(printf "\r")/}

${mean/$(printf "\r")/}

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.

@ruakh相比,此方法的好处在于您在这里仅使用 bash 内置函数。第一个会更快,因为第二个将在子外壳内运行。

If you just want to "unixize" $mean:

如果您只想“统一” $mean:

mean="${mean/^M/}"

mean="${mean/^M/}"

Edit:There's yet anotherway:

编辑:还有另一种方式:

${mean/$'\r'/}

${mean/$'\r'/}

回答by Xaph0d

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.

正如您发现的那样,在 cygwin 中运行 Windows 的东西有一个令人讨厌的副作用 - 在 cygwin bash 变量中捕获 Windows 程序的输出也将捕获程序的 CR 输出。

Judicious use of d2u avoids the issue - for example,

明智地使用 d2u 避免了这个问题 - 例如,

runtime="`mediainfo --Inform='Video;%Duration%' ${movie} | d2u`"

(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.)

(如果没有 d2u,${runtime} 的末尾会附加一个 CR,例如,这会导致您在将其提供给 'bc' 时看到的问题。)

回答by loscuropresagio

Maybe you should just save your script in UNIX format instead of DOS.

也许您应该将脚本保存为 UNIX 格式而不是 DOS。

回答by Elias Dorneles

Try this:

尝试这个:

echo `echo $mean` *1000 |bc

If echo really isn't printing it, it should work.

如果 echo 真的没有打印它,它应该可以工作。

回答by Elias Dorneles

^Mis a carriage returncharacter 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 so bashdoesn'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. dos2unixtool can come handy, for example.

^M是一个回车符,在 Windows 中与换行符 ( \n)一起使用以指示下一行。但是,在 UNIX 世界中它不是这样完成的,因此bash不会将 at 视为特殊字符并破坏语法。您需要做的是使用多种方法之一删除该字符。dos2unix例如,工具可以派上用场。

回答by David W.

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.

正如其他人指出的那样,这是一个 Windows 行结束问题。有很多方法可以解决这个问题,但问题是首先为什么会发生这种情况。

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 texteditor like Notepador Winpad.

  • 这是在 Cygwin 启动时设置的 WINDOWS 环境变量。有时这些变量会在它们的末尾得到一个 CRLF。你提到这是这个变量的一个特殊问题,但你没有指定它的设置位置。

  • 您使用 Windows文本编辑器(如NotepadWinpad )编辑了此文件。

Never use a texteditor to edit a program. Use a program editor. If you like VI, download VIMwhich 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.

切勿使用文本编辑器来编辑程序。使用程序编辑器。如果您喜欢 VI,请下载在 Windows 上可用并在 Cygwin(以及所有其他基于 Unix 的平台)上提供的VIM。如果 VIM 不适合您,请尝试基于图形的Notepad++。这两个编辑器都处理行尾问题,并且可以在 Windows 中创建带有 Unix 行尾的脚本或在 Cygwin 中创建带有 Windows 行尾的文件。



  • If you use VIM, you can do the following to change line endings and to set them:

    • To see the line ending in the current file, type :set ff?while in command mode.
    • To set the line ending for Unix, type :set ff=unixwhile in command mode.
    • To set the line ending for Windows, type :set ff=doswhile in command mode.
  • If you use Notepad++

    • You can go into the Edit-->EOL Conversionmenu item and see what your current line ending setting (it's the one not highlighted) and change it.
    • To have Notepad++ use Unix line endings as the default, go into the Settings-->Preferencesmenu item. In the Dialog box, select the New Document/Default Directorytab. In the Formatsection which is part of the New Documentsection, select the line ending you want. WARNING:Do not select Macas an option. That doesn't even work on Macs. If you have a Mac, select Unix.
  • 如果您使用 VIM,您可以执行以下操作来更改行尾并设置它们:

    • 要查看以当前文件结尾的行,请:set ff?在命令模式下键入。
    • 要为 Unix 设置行结束符,请:set ff=unix在命令模式下键入。
    • 要为 Windows 设置行尾,请:set ff=dos在命令模式下键入。
  • 如果您使用记事本++

    • 您可以进入Edit-->EOL Conversion菜单项,查看您当前的行尾设置(未突出显示的设置)并更改它。
    • 要让 Notepad++ 使用 Unix 行尾作为默认值,请进入Settings-->Preferences菜单项。在对话框中,选择新建文档/默认目录选项卡。在属于新建文档部分的格式部分中,选择所需的行结尾。警告:不要选择作为选项。这甚至不适用于 Mac。如果您有 Mac,请选择MacUnix