Tabs 如何让ksh读取空字段

Tabs 如何让ksh读取空字段,tabs,ksh,delimiter,delimited-text,tab-delimited,Tabs,Ksh,Delimiter,Delimited Text,Tab Delimited,我有一个以制表符分隔的文件,其中一些字段可能不包含任何数据。在ksh中,虽然“read”将多个制表符视为一个分隔符。有没有办法改变这种行为,这样我也可以有空白数据?也就是说,当遇到2个制表符时,是否会将其视为空字段?还是我必须使用awk # where <TAB> would be a real tab: while IFS="<TAB>" read a b c d; do echo $c; done < file.txt 如果第一条或第二条记录为空,shell版

我有一个以制表符分隔的文件,其中一些字段可能不包含任何数据。在ksh中,虽然“read”将多个制表符视为一个分隔符。有没有办法改变这种行为,这样我也可以有空白数据?也就是说,当遇到2个制表符时,是否会将其视为空字段?还是我必须使用awk

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

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

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

echo " b c d e"  | while read a b c d e; do echo c=$c; done
我将继续使用空格作为IFS,只是更容易测试。
通过切割可以避免awk:

echo c=$(echo " b c d e"  | cut -d" " -f3)
当您想在一次运行中分配所有字段时,您将被剪切卡住。
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]="

您信任您的输入,还是更喜欢sed以上的awk?

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

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
typeset-a Cols
而IFS=$'\t\t'读取-A Cols
做
for((i=0;i<${Cols[@]};i++)
做
打印“Cols[$i]'${Cols[$i]}”
完成
完成
是的,这也将正确地将以tab char开头的行视为第1列的null值,即在上述中,Cols[0]将设置为null

我已经在macOS High Sierra上的/bin/ksh“AJM93u+2012-08-01”上对此进行了测试 但它应该与AT&T AST开源ksh版本一起使用,可以追溯到10年或更长时间。另见

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