【问题标题】:BASH: Strip new-line character from string (read line)BASH:从字符串中去除换行符(读取行)
【发布时间】:2010-11-30 08:43:03
【问题描述】:

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

  • 从文件中读取行
  • 从刚刚读取的行尾去掉\n 字符
  • 执行其中的命令

示例: 命令.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

评论说你有我在问之前尝试过的东西。有什么解决办法吗?在过去的几个小时里,我一直在为此绞尽脑汁......

【问题讨论】:

  • 你有没有单独尝试过$line
  • 我当然做到了。但它说“找不到命令:ls”
  • 只需要:myline="$(echo -n "$line")"(如果你愿意,可以用反引号代替$()

标签: windows linux bash samba


【解决方案1】:

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

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

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

【讨论】:

  • 是的,当然,但那部分是我的批处理文件。它不仅仅是一个简单的从文件执行命令,因为如果它只是这个我肯定只使用过sh
【解决方案2】:

您也可以尝试仅使用 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' 

【讨论】:

    【解决方案3】:

    我试过了:

    read line
    echo -n $line | od -x
    

    对于输入“xxxx”,我得到:

    0000000 7878 7878
    

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

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

    【讨论】:

    • 问题是我不从键盘读取。我将我的 STDIN 更改为一个文件(上面的 command.txt),如果我在 '' 之间回显 $line,我会得到输出 'ls'
    • 我在echo -n $line | od -x 上得到的输出是“0000000 736c 000d 0000003”
    • 0d 是回车。与换行符不同
    • 啊!您在 Windows 上编辑了该文件,现在您在其中有了 CR!使用 dos2unix 或类似脚本将 CRLF (0d0a) 转换为 LF (0a)。
    • +1,我知道得更好,但出于某种原因,我使用了 Windows。这有很大帮助。谢谢。
    【解决方案4】:

    你需要 eval 命令

    
    #!/bin/bash -x
    
    while read  cmd
    do
     if [ "$cmd" ]
     then
      eval "$cmd"
     fi
    done
    

    我运行它
    ./script.sh

    而 file.txt 是:

    ls ls -l ls -ltra ps为

    【讨论】:

      【解决方案5】:

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

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

      但是

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

      用我自己的这样的测试脚本(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
      

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

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

      【讨论】:

      • 我忘了提到该文件是从 Windows 在 samba 共享中写入的,我完全忘记了我应该寻找 \r 而不是 \n。我投一票,非常感谢!
      • 感谢您的洞察力。我在 linux 上使用 csv 模式从 sqlite3 生成输出,但输出似乎有 \r\n 终止符。在看到您的评论并意识到这是问题所在之前,我浪费了很多时间......
      【解决方案6】:

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

      #!/bin/bash
      
      while read I ; do if [ "$I" ] ; then $I ; fi ; done ;
      

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 2012-09-13
          • 2013-10-21
          • 2018-08-22
          • 1970-01-01
          • 1970-01-01
          • 2015-06-30
          • 2011-10-13
          • 1970-01-01
          相关资源
          最近更新 更多