拆分文件内容并存储到数组中或通过分隔符遍历文件内容
Split file content and store into array or iterate throgh file content by delimeter
我在下面的文件中说 MemberFile.txt。其中包含由分隔符“#”分隔的记录,分隔符“#”从换行符开始并且是该行的单个字符。因此有3条记录。
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 }' Member.txt))
for i in $arr
do
echo $I
#do something more
done
能不能请你看看哪里不对,指正一下。我很熟悉这个 bash 脚本。我需要对每条记录再次执行一些操作。
使用此 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 }' file
FirstName01
NameFirst02
03FirstName
如果你确实需要使用数组,你可以这样做:
#!/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 的每一行,并在遇到“#”时增加一个计数器,并使用这个计数器创建每个元素保存每个数据块。然后我们遍历数组并打印出每个块,做任何其他需要的事情。
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);
print(join("\0", @records), "\0");' |而 IFS= 读取 -r -d $'\0' 记录;回声"Got record: $record";完成
但是,由于您所做的只是将“#”替换为 null,因此您可以使用 sed 进行此简单替换:
cat Member.txt | sed 's/^#$/\x00/' | while IFS= read -r -d $'[=11=]' record; do echo "Got record: $record"; done
请注意,需要 IFS=
来防止 read
一次只消耗一个单词。 -d $'[=15=]'
将分隔符设置为空字符。 -r
用于原始模式:它告诉 read
忽略数据中的特殊字符。
但我同意 anubhava 的一件事:脚本语言在文本处理方面比 bash 更强大、更有用。我建议使用 perl 而不是 awk,因为 awk 的规则不像普通的编程语言。尽管用 awk 写了大约一百个脚本,但我从来没有掌握它的窍门。我发现调试 awk 脚本很困难,即使有文档在我面前也是如此。 Awk 是一种简单的语言,当您尝试做复杂的事情时它会变得丑陋。 Perl 有一个更陡峭的初始学习曲线,但它很快就不再像黑魔法了。
我在下面的文件中说 MemberFile.txt。其中包含由分隔符“#”分隔的记录,分隔符“#”从换行符开始并且是该行的单个字符。因此有3条记录。
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 }' Member.txt))
for i in $arr
do
echo $I
#do something more
done
能不能请你看看哪里不对,指正一下。我很熟悉这个 bash 脚本。我需要对每条记录再次执行一些操作。
使用此 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 }' file
FirstName01
NameFirst02
03FirstName
如果你确实需要使用数组,你可以这样做:
#!/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 的每一行,并在遇到“#”时增加一个计数器,并使用这个计数器创建每个元素保存每个数据块。然后我们遍历数组并打印出每个块,做任何其他需要的事情。
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);
print(join("\0", @records), "\0");' |而 IFS= 读取 -r -d $'\0' 记录;回声"Got record: $record";完成
但是,由于您所做的只是将“#”替换为 null,因此您可以使用 sed 进行此简单替换:
cat Member.txt | sed 's/^#$/\x00/' | while IFS= read -r -d $'[=11=]' record; do echo "Got record: $record"; done
请注意,需要 IFS=
来防止 read
一次只消耗一个单词。 -d $'[=15=]'
将分隔符设置为空字符。 -r
用于原始模式:它告诉 read
忽略数据中的特殊字符。
但我同意 anubhava 的一件事:脚本语言在文本处理方面比 bash 更强大、更有用。我建议使用 perl 而不是 awk,因为 awk 的规则不像普通的编程语言。尽管用 awk 写了大约一百个脚本,但我从来没有掌握它的窍门。我发现调试 awk 脚本很困难,即使有文档在我面前也是如此。 Awk 是一种简单的语言,当您尝试做复杂的事情时它会变得丑陋。 Perl 有一个更陡峭的初始学习曲线,但它很快就不再像黑魔法了。