【问题标题】:BASH: How to read TAB-separated line with empty colums from file into arrayBASH:如何将带有空列的制表符分隔行从文件读入数组
【发布时间】:2021-06-03 10:19:20
【问题描述】:

应分析一个 txt 文件:它有很多行,每行有 20 个由 TAB 分隔的字段,每个字段可以包含任何类型的数据(整数、浮点数、日期时间、文本也包含空白和“”等),并且在除此之外,字段可以为空,例如这样一行的开头就像

111TABTABWalterTAB11.1234TABThis is a sample TextTAB"Another sample"TABTABTAB555...

如何将文件的每一行读入具有 20 列的数组 arrLine,例如

  • arrLine(0)=111
  • arrLine(1)=
  • arrLine(2)=沃尔特
  • ...

我试过this proposal喜欢

while IFS=$'\t' read -r -a arrLine; do
    echo "${#arrLine[@]} items: ${arrLine[@]}"
    echo "${arrLine[3]} || ${arrLine[4]} || ${arrLine[5]}"
done < "test.txt"

但空列没有填充到数组中。

谢谢!

【问题讨论】:

  • 添加了我的实际代码(来自 StackOverflow),但它不考虑空单元格

标签: arrays bash tabs


【解决方案1】:

IFS="anyWithespaceCharacter" read 无法读取其他两个字段之间的空字段;对于非空白字符,这将起作用。这种不一致的行为是由posix 决定的:

术语“IFS 空白”用于表示 IFS 值中的空白字符的任何序列(零个或多个实例)(例如,如果 IFS 包含 //,任何 字符序列都被视为 IFS 空白)。

  • 应忽略输入开头和结尾的 IFS 空格。
  • 输入中出现的不是 IFS 空白的 IFS 字符的每次出现,以及任何相邻的 IFS 空白,都应分隔一个字段,如前所述。
  • 非零长度 IFS 空白应分隔字段。

但您仍然可以使用mapfile 将每一行拆分为字段:

while IFS= read -r line; do
    mapfile -td $'\t' arrLine < <(printf %s "$line")
    declare -p arrLine # prints the array for debugging
done < test.txt

或者,将空白分隔符(在本例中为制表符)交换为输入中未出现的任何其他非空白字符。在这种情况下,我们使用 ascii 符号 “单位分隔符” \037

while IFS=$'\037' read -ra arrLine; do
    declare -p arrLine # prints the array for debugging
done < <(tr \\t \\037 < test.txt)

【讨论】:

  • 为了可视化数组 arrLine 的内容,我推荐:declare -p arrLine
  • 谢谢 Socowi,看起来很完美。 @Cyrus:我不明白你的评论,在哪里添加代码?
  • @StOMicha:要快速了解数组 arrLine 中的内容,您可以使用 echo 删除两行并在其中添加一个 declare -p arrLine
  • 感谢 Cyrus,非常适合调试!
  • @Socowi 如果该行已经包含 单位分隔符 (\037) 字符(不寻常,但并非不可能),则替代解决方案可能不起作用。但有一个补救措施:将tr \\t \\037 替换为tr '\t\037' '\037\t' 并将其添加为while 循环中的第一行:arrLine=("${arrLine[@]//$'\t'/$'\037'}")
【解决方案2】:

您可以使用 IFS 将输入行拆分为数组,但在这种情况下,bash 想要全局制表符,因此如果有连续的制表符,则会丢失列。您可以通过将制表符转换为不同的分隔符来回避这一点。

#IFS=$'\t'
IFS='|'
while read -a arrLine; do
  for i in {0..19}; do
    echo "arrLine [$i]: ${arrLine[$i]}"
  done
done < <(cat input.txt | tr '\t' '|')

arrLine [0]: 111
arrLine [1]:
arrLine [2]: Walter
arrLine [3]: 11.1234
arrLine [4]: This is a sample Text
arrLine [5]: "Another sample"
arrLine [6]:
arrLine [7]:
arrLine [8]: 555...
arrLine [9]:
arrLine [10]:
etc.....

【讨论】:

    猜你喜欢
    • 2012-04-01
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多