Linux BASH:从字符串中去除换行符(读取行)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1459250/
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-08-03 17:43:16  来源:igfitidea点击:

BASH: Strip new-line character from string (read line)

windowslinuxbashsamba

提问by Bogdan Constantinescu

I bumped into the following problem: I'm writing a Linux bash script which does the following:

我遇到了以下问题:我正在编写一个 Linux bash 脚本,它执行以下操作:

  • Read line from file
  • Strip the \ncharacter from the end of the line just read
  • Execute the command that's in there
  • 从文件中读取行
  • \n从刚读过的行尾去掉字符
  • 执行里面的命令

Example: commands.txt

示例:commands.txt

ls
ls -l
ls -ltra
ps as

The execution of the bash file should get the first line, and execute it, but while the \npresent, the shell just outputs "command not found: ls" That part of the script looks like this

bash文件的执行应该拿到第一行,然后执行,但是\n现在shell只输出“command not found:ls”那部分脚本是这样的

 read line

        if [ -n "$line" ]; then #if not empty line

                #myline=`echo -n $line | tr -d '\n'`
                #myline=`echo -e $line | sed ':start /^.*$/N;s/\n//g; t start'`

                myline=`echo -n $line | tr -d "\n"`
                $myline  #execute it

                cat $fname | tail -n+2 > $fname.txt
                mv $fname.txt $fname
        fi

Commented you have the things I tried before asking SO. Any solutions? I'm smashing my brains for the last couple of hours over this...

评论说你有我在问 SO 之前尝试过的东西。任何解决方案?在过去的几个小时里,我正在为此绞尽脑汁......

采纳答案by cms

I always like perl -ne 'chomp and print', for trimming newlines. Nice and easy to remember.

我总是喜欢perl -ne 'chomp and print', 用于修剪换行符。好记又好记。

e.g. ls -l | perl -ne 'chomp and print'

例如 ls -l | perl -ne 'chomp and print'

However

然而

I don't think that is your problem here though. Although I'm not sure I understand how you're passing the commands in the file through to the 'read' in your shell script.

我不认为这是你的问题。虽然我不确定我是否理解您如何将文件中的命令传递到 shell 脚本中的“读取”。

With a test script of my own like this (test.sh)

使用我自己的测试脚本(test.sh)

read line
if [ -n "$line" ]; then
  $line
fi

and a sample input file like this (test.cmds)

和这样的示例输入文件(test.cmds)

ls 
ls -l
ls -ltra

If I run it like this ./test.sh < test.cmds, I see the expected result, which is to run the first command 'ls' on the current working directory.

如果我像这样运行它./test.sh < test.cmds,我会看到预期的结果,即在当前工作目录上运行第一个命令 'ls'。

Perhaps your input file has additional non-printable characters in it ?

也许您的输入文件中有额外的不可打印字符?

mine looks like this

我的看起来像这样

od -c test.cmds 
0000000    l   s      \n   l   s       -   l  \n   l   s       -   l   t
0000020    r   a  \n                                                    
0000023

From your comments below, I suspect you may have carriage returns ( "\r" ) in your input file, which is not the same thing as a newline. Is the input file originally in DOS format ? If so, then you need to convert the 2 byte DOS line ending "\r\n" to the single byte UNIX one, "\n" to achieve the expected results.

根据您下面的评论,我怀疑您的输入文件中可能有回车符 ( "\r" ),这与换行符不同。输入文件最初是 DOS 格式吗?如果是这样,那么您需要将以“\r\n”结尾的 2 字节 DOS 行转换为单字节 UNIX 行“\n”以达到预期的结果。

You should be able to do this by swapping the "\n" for "\r" in any of your commented out lines.

您应该能够通过在任何注释掉的行中将 "\n" 交换为 "\r" 来做到这一点。

回答by knittl

though not working for ls, I recommend having a look at find's -print0option

虽然不工作ls,我建议看看find-print0选项

回答by Aaron Digulla

I tried this:

我试过这个:

read line
echo -n $line | od -x

For the input 'xxxx', I get:

对于输入'xxxx',我得到:

0000000 7878 7878

As you can see, there is no \nat the end of the contents of the variable. I suggest to run the script with the option -x(bash -x script). This will print all commands as they are executed.

如您所见,\n变量内容的末尾没有。我建议使用选项-x( bash -x script)运行脚本。这将在执行时打印所有命令。

[EDIT] Your problem is that you edited commands.txt on Windows. Now, the file contains CRLF (0d0a) as line delimiters which confuses read(and ls\ris not a known command). Use dos2unixor similar to turn it into a Unix file.

[编辑] 你的问题是你在 Windows 上编辑了 commands.txt。现在,该文件包含 CRLF (0d0a) 作为令人困惑的行分隔符read(并且ls\r不是已知命令)。使用dos2unix或 类似方法将其转换为 Unix 文件。

回答by sud03r

you need eval command

你需要 eval 命令


#!/bin/bash -x

while read  cmd
do
 if [ "$cmd" ]
 then
  eval "$cmd"
 fi
done

I ran it as
./script.sh < file.txt

我将它作为
./script.sh < file.txt 运行

And file.txt was:

而 file.txt 是:

ls
ls -l
ls -ltra
ps as

回答by dsm

The following script works (at least for me):

以下脚本有效(至少对我而言):

#!/bin/bash

while read I ; do if [ "$I" ] ; then $I ; fi ; done ;

回答by Mark Edgar

Someone already wrote a program which executes shell commands: sh file

有人已经写了一个执行shell命令的程序:sh file

If you really only want to execute the first line of a file: head -n 1 file |sh

如果您真的只想执行文件的第一行: head -n 1 file |sh

If your problem is carriage-returns: tr -d '\r' <file |sh

如果您的问题是回车: tr -d '\r' <file |sh

回答by Mark Edgar

You may also try to replace carriage returns with newlines only using Bash builtins:

您也可以尝试仅使用 Bash 内置函数用换行符替换回车符:

line=$'a line\r' 
line="${line//$'\r'/$'\n'}" 
#line="${line/%$'\r'/$'\n'}"       # replace only at line end
printf "%s" "$line" | ruby -0777 -n -e 'p $_.to_s'