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

发布于 2024-12-18 18:28:41 字数 381 浏览 2 评论 0原文

我的性格有问题。我认为这是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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

荭秂 2024-12-25 18:28:41

我手边没有 Cygwin,但在常规 Bash 中,您可以使用 tr -d 命令来删除指定字符,并且可以使用 $'...' 表示法在命令行参数中指定奇怪的字符(它就像普通的单引号字符串,只是它支持 C/Java/Perl/等类似的转义序列)。因此,这

echo "$mean" * 1000 | tr -d 

将删除从 echobc 途中的回车符。

您实际上可能想运行此命令:

mean=$(echo "$mean" | tr -d 

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

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

\r' | bc

将删除从 echobc 途中的回车符。

您实际上可能想运行此命令:


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

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

\r')

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

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

\r' | bc

将删除从 echobc 途中的回车符。

您实际上可能想运行此命令:

它将修改 $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:

echo "$mean" * 1000 | tr -d 

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

You might actually want to run this:

mean=$(echo "$mean" | tr -d 

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

\r' | bc

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

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

\r')

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

\r' | bc

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

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

深海不蓝 2024-12-25 18:28:41

这有效:

${mean/^M/}

您可以通过依次键入 Ctrl-V 和 Ctrl-M 来获取 ^M。或者,另一种选择:

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

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

如果你只是想“unixize”$mean:

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

编辑:还有另一种方法:

${mean/$'\r'/}

This works:

${mean/^M/}

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

${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.

If you just want to "unixize" $mean:

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

Edit: There's yet another way:

${mean/$'\r'/}

流心雨 2024-12-25 18:28:41

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

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

runtime="`mediainfo --Inform='Video;%Duration%' ${movie} | 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,

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

沫雨熙 2024-12-25 18:28:41

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

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

毅然前行 2024-12-25 18:28:41

试试这个:

echo `echo $mean` *1000 |bc

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

Try this:

echo `echo $mean` *1000 |bc

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

玩套路吗 2024-12-25 18:28:41

^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 so bash 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.

乖乖哒 2024-12-25 18:28:41

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

我可以在几个地方看到这种情况发生:

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

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

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


  • 如果您使用 VIM,您可以执行以下操作来更改行结尾并进行设置:

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

    • 您可以进入编辑-->EOL 转换菜单项,查看当前的行结束设置(未突出显示的设置)并进行更改。
    • 要让 Notepad++ 使用 Unix 行结尾作为默认值,请进入“设置 --> 首选项”菜单项。在对话框中,选择“新建文档/默认目录”选项卡。在属于新文档部分的格式部分中,选择所需的行结尾。 警告:请勿选择 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:

    • 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=unix while in command mode.
    • To set the line ending for Windows, type :set ff=dos while in command mode.
  • If you use Notepad++

    • You can go into the Edit-->EOL Conversion menu 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-->Preferences menu item. In the Dialog box, select the New Document/Default Directory tab. In the Format section which is part of the New Document section, select the line ending you want. WARNING: Do not select Mac as an option. That doesn't even work on Macs. If you have a Mac, select Unix.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文