BASH:从字符串中去除换行符(读取行)
我遇到了以下问题:我正在编写一个 Linux bash 脚本,该脚本执行以下操作:
- 从文件中读取行
- 从刚刚读取的行末尾去除
\n
字符 - 执行其中的命令
例子: Commands.txt
ls
ls -l
ls -ltra
ps as
bash 文件的执行应该获取第一行并执行它,但是当 \n
存在时,shell 只输出“command not find: 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
评论你在询问之前已经尝试过的事情。有什么解决办法吗?过去几个小时我都在为这事绞尽脑汁……
I bumped into the following problem: I'm writing a Linux bash script which does the following:
- Read line from file
- Strip the
\n
character from the end of the line just read - Execute the command that's in there
Example:
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 \n
present, the shell just outputs "command not found: ls"
That part of the script looks like this
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...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我总是喜欢
perl -ne 'chomp and print'
来修剪换行符。很好而且很容易记住。例如 ls -l | perl -ne 'chomp and print'
但是
我不认为这是你的问题。尽管我不确定我是否理解您如何将文件中的命令传递给 shell 脚本中的“读取”。
使用我自己的测试脚本(test.sh)
和示例输入文件(test.cmds)
如果我像这样运行它
./test.sh
./test.sh < test.cmds
,我看到了预期的结果,即在当前工作目录上运行第一个命令“ls”。也许您的输入文件中有其他不可打印的字符?
我的看起来像这样
从下面的评论中,我怀疑您的输入文件中可能有回车符(“\r”),这与换行符不同。输入文件原来是DOS格式的吗?如果是这样,那么您需要将以“\r\n”结尾的 2 字节 DOS 行转换为单字节 UNIX 行“\n”才能达到预期结果。
您应该可以通过在任何注释掉的行中将“\n”替换为“\r”来完成此操作。
I always like
perl -ne 'chomp and print'
, for trimming newlines. Nice and easy to remember.e.g.
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.
With a test script of my own like this (test.sh)
and a sample input file like this (test.cmds)
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.Perhaps your input file has additional non-printable characters in it ?
mine looks like this
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.
You should be able to do this by swapping the "\n" for "\r" in any of your commented out lines.
有人已经编写了一个执行 shell 命令的程序: sh file
如果您确实只想执行文件的第一行:
head -n 1 file |sh
如果您的问题是回车符:
tr -d '\r' <文件 |sh
Someone already wrote a program which executes shell commands: sh file
If you really only want to execute the first line of a file:
head -n 1 file |sh
If your problem is carriage-returns:
tr -d '\r' <file |sh
您还可以尝试仅使用 Bash 内置命令将回车符替换为换行符:
You may also try to replace carriage returns with newlines only using Bash builtins:
我尝试了以下操作:
对于输入“xxxx”,我得到:
如您所见,变量内容的末尾没有
\n
。我建议使用选项-x
(bash -x script
)运行脚本。这将在执行时打印所有命令。[编辑] 您的问题是您在Windows 上编辑了commands.txt。现在,该文件包含 CRLF (0d0a) 作为行分隔符,这会混淆
read
(并且ls\r
不是已知命令)。使用 dos2unix 或类似工具将其转换为 Unix 文件。I tried this:
For the input 'xxxx', I get:
As you can see, there is no
\n
at 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.[EDIT] Your problem is that you edited commands.txt on Windows. Now, the file contains CRLF (0d0a) as line delimiters which confuses
read
(andls\r
is not a known command). Usedos2unix
or similar to turn it into a Unix file.你需要 eval 命令,
我将其运行为
./script.sh < file.txt 文件
.txt 是:
you need eval command
I ran it as
./script.sh < file.txt
And file.txt was:
虽然不适用于
ls
,但我建议您查看查找
的-print0
选项though not working for
ls
, I recommend having a look atfind
’s-print0
option以下脚本有效(至少对我来说):
The following script works (at least for me):