【问题标题】:Split file content and store into array or iterate throgh file content by delimeter拆分文件内容并存储到数组中并通过分隔符遍历文件内容
【发布时间】:2017-07-13 10:39:38
【问题描述】:

我有下面的文件说 MemberFile.txt。其中包含由分隔符“#”分隔的记录,该分隔符从换行符开始,是该行的单个字符。因此一共有三个记录。

3RECORDSFILE
#
[FIRSTNAME      ]   FirstName01
[MIDDLENAME     ]   MiddleName01
[LASTNAME       ]   LastName01
[ADDRESS       Q]   AddressOf #001 Pune
[ADDRESS       S]   AddressOf #001
#
[FIRSTNAME      ]   NameFirst02
[MIDDLENAME     ]   MiddleName02
[LASTNAME       ]   LastName02
[ADDRESS       Q]   AddressOf [002
[ADDRESS       N]   Addres Mumbai sOf [002
#
[FIRSTNAME      ]   03FirstName
[MIDDLENAME     ]   MiddleName03
[LASTNAME       ]   LastName03
[ADDRESS       Q]   Address Of 003]

我们如何在没有cat 整个文件的情况下使用 IFS 遍历记录。我在下面尝试了一些无济于事的事情。看起来它是逐行而不是按指定的 IFS 读取的。不知道哪里错了。

#!/bin/bash
while IFS='^#$' read r
do
echo $r
#do something more
done < MemberFile.txt

我尝试使用 awk 的其他选项。指定分隔符并存储到数组中。这也没有产生预期的结果。

arr=($(awk -F='^#$' '{print $1}' Member.txt))
for i in $arr
do
echo $I
#do something more
done

请您看看并纠正我哪里出错了。我对这个 bash 脚本很陌生。我需要对每条记录再次执行一些操作。

【问题讨论】:

    标签: linux bash awk ifs


    【解决方案1】:

    使用此gnu awk 将输入分解为由#\n 分隔的记录:

    awk -v RS='#\n' 'NR>1{print "==================", NR, "================"; print}' file
    ================== 2 ================
    [FIRSTNAME      ]   FirstName01
    [MIDDLENAME     ]   MiddleName01
    [LASTNAME       ]   LastName01
    [ADDRESS       Q]   AddressOf #001 Pune
    [ADDRESS       S]   AddressOf #001
    
    ================== 3 ================
    [FIRSTNAME      ]   NameFirst02
    [MIDDLENAME     ]   MiddleName02
    [LASTNAME       ]   LastName02
    [ADDRESS       Q]   AddressOf [002
    [ADDRESS       N]   Addres Mumbai sOf [002
    
    ================== 4 ================
    [FIRSTNAME      ]   03FirstName
    [MIDDLENAME     ]   MiddleName03
    [LASTNAME       ]   LastName03
    [ADDRESS       Q]   Address Of 003]
    

    您可以对每条记录进行操作,例如使用此 awk 命令打印所有 FIRSTNAME

    awk -v RS='#\n' 'NR>1{print $3}' file
    
    FirstName01
    NameFirst02
    03FirstName
    

    【讨论】:

    • 它的工作 Anubhava。如何将整个记录存储到变量中。
    • 需要 '\r\n' 而不是 '\n'。对不起,盲目地跑,没有改变
    • 为什么要存储每条记录?无论您想做什么处理,都可以在 awk 中进行。不要让bash 参与其中。
    • 可能是我无法使用 awk 获得它。你能帮忙吗?如何在大括号中实现同样的效果。 awk -v RS='#\n' 'NR&gt;1{ #Get FIRSTNAME value and store into variable, # Check if record contains Mumbai or Pune and echo "YES"}' file
    • 花一些时间阅读一个好的 awk 教程。您可以使用:awk -v RS='#\n' 'NR&gt;1 &amp;&amp; /Mumbai|Pune/{print "YES"}' file 来完成您的要求。我已经提供了一个示例来获取所有 FIRSTNAME 字段。
    【解决方案2】:

    如果您确实需要使用数组,可以执行以下操作:

    #!/bin/bash
    arry=""
    cnt=0
    while read -r line
    do
            if [[ "$line" == "#" ]]
            then
                    cnt=$(($cnt+1))
            else
                    arry[$cnt]=${arry[$cnt]}$line"\n"
            fi
    done < Member.txt
    for ((i=1;i<=$cnt;i++))
    do
            echo -e ${arry[$i]}
            # do some other stuff here
    done
    

    我们首先在循环中获取 Member.txt 的每一行,并在遇到“#”时增加一个计数器,并使用这个计数器来创建每个包含每个数据块的元素。然后我们循环遍历数组并打印出每个块,做其他需要的事情。

    【讨论】:

    • 嗨拉曼,虽然这很好用……对我来说,性能很重要。
    【解决方案3】:

    anubhava 的答案似乎很有用,但如果您需要将输入输入 bash 变量,则实际上并不存在。整个过程是将记录读入脚本语言(就像 anubhava 所做的那样),然后用空分隔符打印记录,然后将记录读入 bash 变量。使用空分隔符,因为您知道文本不会包含空值。关键是让read 命令使用空字符作为其分隔符。

    我在第一部分使用 perl 而不是 awk:

    cat Member.txt | perl -e 'use warnings; use strict; my $stdin_raw; { local $/; $stdin_raw = <STDIN>; }; my @records = split(/\n#/m, $stdin_raw);
    

    打印(加入(“\0”,@records),“\0”);' |而 IFS= 读取 -r -d $'\0' 记录;做回声“得到记录:$记录”;完成

    但是,由于您所做的只是将“#”替换为 null,因此您可以使用 sed 进行这个简单的替换:

    cat Member.txt | sed 's/^#$/\x00/' | while IFS= read -r -d $'\0' record; do echo "Got record: $record"; done
    

    请注意,需要IFS= 以防止read 一次只使用一个单词。 -d $'\0' 将分隔符设置为空字符。 -r 用于原始模式:它告诉 read 忽略数据中的特殊字符。

    但我同意 anubhava 关于一件事:脚本语言在文本处理方面比 bash 更强大、更有用。我建议使用 perl 而不是 awk,因为 awk 的规则不像普通的编程语言。尽管在 awk 中编写了大约一百个脚本,但我始终没有掌握它的窍门。我发现调试 awk 脚本很困难,即使有我面前的文档也是如此。 awk 是一种简单的语言,当你尝试做复杂的事情时会变得很丑。 Perl 的初始学习曲线更陡峭,但它很快就不再像黑魔法了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 1970-01-01
      相关资源
      最近更新 更多