【问题标题】:newline character in POSIX shellPOSIX shell 中的换行符
【发布时间】:2014-03-19 19:22:32
【问题描述】:

我正在解析 avahi-browse 工具的输出,我的脚本应该与 POSIX 兼容。

接下来我会这样做:

      local _dnssd=`avahi-browse -apt`
      if [ -z "$_dnssd" ]; then
        echo "No info"
      else
        IFS='
    ' # it's new line character in IFS
        for _row in $_dnssd
         do  
          local _tmpIFP="$IFS"
          IFS=";"
            case "$_row" in
            ...
            esac
            IFS="$_tmpIFS"
        done
      fi  

我真的不喜欢将换行符分配给 IFS。是否有可能以更好的方式替换它?

我尝试了stackoverflow的一些建议,但没有奏效:

IFS=$(echo -e '\n')

avahi-浏览输出:

+;br0;IPv4;switch4B66E4;_http._tcp;local
+;br0;IPv4;switch4B66E4;_csco-sb._tcp;local

【问题讨论】:

  • 我猜你可以使用IFS=$'\n'
  • fedorqui,我不能使用任何 bashism。它将在 POSIX shell 上执行。
  • local 也不是 POSIX shell 的一部分。

标签: shell unix scripting


【解决方案1】:

如果可以相信* IFS 有它的默认值(空格、制表符、换行符),那么可以简单地去掉前两个字符(空格和制表符),换行符将保留:

IFS=${IFS#??}

*如果IFS之前没有被脚本修改过并且是POSIX shell(正如主题所暗示的那样),你可以依赖它:

shell 在调用时应将 IFS 设置为

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03

【讨论】:

    【解决方案2】:

    最好使用while 循环而不是尝试遍历包含整个输出的字符串。

    avahi-browse -apt | while IFS=";" read field1 field2 ...; do
        case ... in
        ...
        esac
    done
    

    请注意,read 命令的每个字段都需要一个名称。 ... 只是一个占位符,对于可变数量的字段不是有效的 shell 语法。

    如果程序没有输出,这根本就什么都不做。如果您确实需要检测这种情况,请尝试

    avahi-browse -apt | {
        read line || { echo "No info"; exit; }
        while : ; do
            IFS=";" read field1 field2 ... <<EOF
            $line
    EOF
            case ... in
            ...
            esac
            read line || break
        done
    }
    

    在这两种情况下,设置在管道右侧的任何变量都是该 shell 的本地变量。如果您需要设置变量以供以后使用,则需要进行一些进一步的调整。

    【讨论】:

    • 如果字段可以包含空格,例如 =;eth0;IPv4;\039s\032remote\032desktop\032on\032O;VNC Remote Access;local;O.local;192.168.26.19;5900。在 IFS=";" 之后不可能检测到整个字段。
    • 通过将IFS 设置为分号,空格将被视为字段的一部分,而不是字段分隔符。
    【解决方案3】:

    IFS 变量中的\n 之后添加一个空格,然后再次删除该空格:

    IFS="$(printf '\n ')" && IFS="${IFS% }"
    #IFS="$(printf '\n ')" && IFS="${IFS%?}"
    printf '%s' "$IFS" | od -A n -c 
    

    【讨论】:

      猜你喜欢
      • 2016-05-24
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-03
      • 2021-04-21
      • 2016-12-12
      • 2018-12-05
      相关资源
      最近更新 更多