2011-11-29 67 views
5

我有一个字符问题。我认为这是dos和unix之间的转换问题。Bash programmation(Cygwin):非法字符^ M

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

0.495959 

但是,当我试图让与bc命令是值的操作(我不知道如何写bc命令)。

echo $mean *1000 |bc 

我得到:

(standard_in) 1 : illegal character: ^M 

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

我该如何消除这个错误?

+0

'$ mean'是如何获得的? – netcoder

+0

使用ImageMagick“识别”命令。但是,因为我在Windows上,它可能会以DOS格式而不是Unix格式输出结果。什么导致一个马车角色被添加。? – Frencoo

+0

好的,但是你运行的命令是什么,所以'$ mean'被填充了?像'mean = \'识别... \''...我们需要整条线。 – netcoder

回答

11

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

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

将去掉回车符号的方式,从echobc

你可能真的要运行此:

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

将修改$mean里面剔除任何回车符号,然后你将不必担心在使用它以后的命令。

(虽然它也是值得考虑看看那台$mean开始。如何$mean最终不得不在它回车的代码啊?也许你可以解决这个问题。)

+0

Thans很多人,它的作品! – Frencoo

1

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

+0

我已经使用dos2unix命令将其转换。这是你的意思吗? – Frencoo

+0

是的。我不知道为什么使用dos2unix不能解决您的问题。代码看起来不错。我试过了,它工作正常。但是,如果我在DOS模式下保存脚本,我会得到相同的错误:'(standard_in)1:非法字符:^ M'。通常我不使用dos2unix,只是因为我更喜欢编辑器。要复制你的代码,我使用[pspad](http://www.pspad.com)。它的免费,也许你可以试试看。 – loscuropresagio

+0

谢谢你我会尝试pspad – Frencoo

0

试试这个:

echo `echo $mean` *1000 |bc 

如果真的回声不打印,它应该工作。

+2

这是一个很好的想法,但它不会帮助。如果'$ mean'包含'^ M',并且Bash将'^ M'识别为一个字词分隔符(默认情况下它不*),那么'echo $ mean * 1000'将会使'^ M ',因为'$ mean'没有被引用。如果*是*'echo',那就是添加'^ M',那么它显然不会工作(如你所知道的),如果变量'^ M'和Bash *不能识别它作为一个单词分隔符,那么内部的'echo'将仍然打印'^ M',而外部的'echo'将重复它 - 没有增加。 – ruakh

+0

@ruakh你是对的,我没有想到它通过! – elias

0

^M是在Windows中使用的carriage return字符以及用于指示下一行的换行符(\n)字符。然而,它不是在UNIX世界中如何完成的,因此bash不会视为特殊字符,并且会破坏语法。你需要做的是使用许多方法之一删除该字符。例如,dos2unix工具可以派上用场。

+0

正如我所说,我已经在我的.sh文件中使用了dos2unix命令。 这是什么意思或我必须以另一种方式使用? – Frencoo

2

该作品:

${mean/^M/}

您可以通过输入Ctrl-V,然后按Ctrl-M来获得^ M。或者,也可以使用:

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

这种方法相比,@ruakh的好处是,只有在这里你正在使用bash内置插件。第一个将会更快,因为第二个将在子shell中运行。

如果你只是想 “unixize” $平均:

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

编辑:又一方式:

${mean/$'\r'/}

0

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

我可以看到这种情况出现在好几个地方:

  • 这是当Cygwin的启动已设置Windows环境变量。有时候这些变量会在它们的最后得到一个CRLF。你提到这是这个变量的一个特殊问题,但是你没有指定它的设置。

  • 您编辑使用的是Windows 文本编辑这个文件好像记事本Winpad

切勿使用文本编辑器编辑程序。使用程序编辑器。如果你喜欢VI,下载VIM这是在Windows上可用,并在Cygwin(和所有其他基于Unix的平台)。如果VIM不适合你,请尝试更多图形化的Notepad++。这两种编辑器都处理行尾问题,并且可以在Windows中使用Unix行结尾创建脚本,或者在Cygwin中使用Windows行结尾创建脚本。


  • 如果你使用VIM,你可以做以下改变行结尾,并对其进行设置:

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

    • 您可以进入编辑 - > EOL转换菜单项,然后看看你的结局设置当前行(它不是强调一个),并改变它。
    • 要让Notepad ++使用Unix行尾作为默认值,请进入设置 - >首选项菜单项。在对话框中,选择新建文档/默认目录选项卡。在格式部分,它是新文档部分的一部分,请选择您想要的结束行。 警告:请勿选择Mac作为选项。这在Mac上甚至不起作用。如果您有Mac,请选择Unix
+0

谢谢,我会试试看。顺便说一句,我用的是写字板,这可能会导致问题.. – Frencoo

1

Cygwin中运行Windows的东西有,你发现了一个讨厌的副作用 - 捕获Windows程序的输出一个cygwin bash的变量也将捕捉程序输出CR。

明智地使用D2U的避免了这一问题 - 例如,

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

(不D2U,$ {运行}将有CR上涨了年底,这会导致你看到的,当你给它的问题以'bc'为例。)