【问题标题】:How to get ksh to read null fields如何让 ksh 读取空字段
【发布时间】:2015-02-26 14:56:15
【问题描述】:

我有一个制表符分隔的文件,其中一些字段可能不包含数据。在 ksh 'read' 中,虽然将多个制表符视为一个分隔符。有没有办法改变这种行为,所以我也可以有空白数据? IE。当遇到 2 个选项卡时,它会将其视为空字段吗?还是我必须使用 awk?

# where <TAB> would be a real tab:
while IFS="<TAB>" read a b c d; do echo $c; done < file.txt

参照

awk -F"\t" '{print $3}' file.txt

如果第一条或第二条记录为空,shell版本会输出错误的字段。

【问题讨论】:

    标签: tabs ksh delimiter csv


    【解决方案1】:

    确实可以在本地使用现代 Korn Shell 将每个制表符字符视为列分隔符,这样多个连续制表符将在没有 sed、awk 或 perl 的情况下分隔空字段。 诀窍是将 IFS 变量设置为 2 个连续的制表符,如下所示:

    IFS=$'\t\t'
    

    以下代码中的 while 循环将读取一个制表符分隔值文件,将每一行的字段放入一个简单的索引数组中。 内部 for 循环简单地打印出它读取的内容,每行输出一个字段:

    typeset -a Cols
    
    while IFS=$'\t\t' read -A Cols
    do
        for (( i=0 ; i < ${#Cols[@]} ; i++ ))
        do
            print "Cols[$i] '${Cols[$i]}' "
        done
    done
    

    是的,这也将正确地将带有制表符字符的行开始视为第1列具有空值,即在上面的Cols[0]中设置为空。

    我在 macOS High Sierra 上的 /bin/ksh 'AJM93u+ 2012-08-01' 上对此进行了测试 但它应该适用于 10 年或更长时间的 AT&T AST 开源 ksh 版本。另见https://github.com/att/ast

    【讨论】:

      【解决方案2】:

      read 将查找第一个字段,忽略 IFS。这个问题的另一个证明是

      echo " b c d e"  | while read a b c d e; do echo c=$c; done
      

      我将继续使用空间作为 IFS,只是更容易测试。
      使用 cut 可以避免 awk:

      echo c=$(echo " b c d e"  | cut -d" " -f3)
      

      如果您想在一次运行中分配所有字段,您将被 cut 卡住。
      Sed 接受不同的 -e 选项并按照给定的顺序处理它们。 您可以通过

      获取字段
      eval $(echo " b c d e"  | 
         sed -e 's/^/a=/' -e 's/ /;b=/' -e 's/ /;c=/' -e 's/ /;d=/' -e 's/ /;e=/')
      echo check:
      set | grep "^[a-e]="
      

      您相信自己的意见还是更喜欢 awk 而不是 sed?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-11
        • 2020-03-24
        • 2014-02-11
        • 2015-10-20
        相关资源
        最近更新 更多