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

时间:2009-09-22 10:20:56

标签: windows linux bash samba

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

  • 从文件中读取行
  • 从刚刚阅读的行末尾删除\n个字符
  • 执行那里的命令

实施例: commands.txt中

ls
ls -l
ls -ltra
ps as

执行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

评论说,在问SO之前,我已经尝试了一些事情。有解决方案吗在过去的几个小时里,我正在粉碎我的大脑...

7 个答案:

答案 0 :(得分:17)

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

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

<强>然而

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

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

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

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

ls 
ls -l
ls -ltra

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

也许您的输入文件中还包含其他不可打印的字符?

我看起来像这样

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

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

您应该可以通过在任何注释掉的行中交换“\ n”来表示“\ n”。

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:2)

我试过了:

read line
echo -n $line | od -x

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

0000000 7878 7878

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

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

答案 3 :(得分:2)

您也可以尝试仅使用Bash builtins替换回车换行:

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' 

答案 4 :(得分:1)

你需要eval命令


#!/bin/bash -x

while read  cmd
do
 if [ "$cmd" ]
 then
  eval "$cmd"
 fi
done
我按原样跑了 ./script.sh&lt; file.txt

file.txt是:

ls
ls -l
ls -ltra
ps as

答案 5 :(得分:0)

虽然不适用于ls,但我建议您查看find-print0选项

答案 6 :(得分:0)

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

#!/bin/bash

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