我有一些文件的内容随着文件的不同而变化。每个文件有两段行,由一个空行分隔。我永远不知道这两个部分有多少行或字符。
该文件可能看起来像这样。
This is a file
with some text
and some more text
此代码只给出每个部分的第一行。
awk 'BEGIN {RS="nn"; FS="n";} {print $1 }' file
我需要把每一部分都分开来处理。
打印第一部分:sed '/^$/q' test.txt
打印第二部分:sed '1,/^$/d' test.txt
由于这被标记为bash
,所以不妨有一个本地bash解决方案。
sections=( )
current_section=
while REPLY=; IFS= read -r || [[ $REPLY ]]; do
if [[ $REPLY ]]; then
# preserve newlines within the sections
if [[ $current_section ]]; then
current_section+=$'n'"$REPLY"
else
current_section+=$REPLY
fi
else
sections+=( "$current_section" )
current_section=
fi
done <file
这将把文件的各个部分放入一个名为sections
的bash数组中。
您可以打印该数组的内容,如下所示:
printf -- '---n%sn---n' "${sections[@]}"
或者重复它,随心所欲:
for section in "${sections[@]}"; do
: do something with "$section" here
done
将RS
设置为null/blank值,以使awk对空行序列进行操作。
来自awk的POSIX规范:
RS
RS字符串值的第一个字符应为输入记录分隔符;默认情况下为a。如果RS包含多个字符,则未指定结果如果RS为空,则记录由一个或多个空行组成的序列分隔,前导或尾随空行不会在输入的开始或结束处导致空记录,并且无论FS的值是多少,a都应始终是字段分隔符。
IFS=";"
sections=($(awk -v RS= '{print $0 ";"}' filename))
IFS=;
将内部字段分隔符从空格(默认值(设置为分号
$(awk -v RS= '{print $0 ";"}' filename)
打印出由两条新行分隔的部分,并在每个部分之后输出;
。实现相同结果的另一种方法是awk -v ORS=';' -v RS= '{print}'
sections=(awk_output_here)
基于IFS
对awk输出进行分割,并将每个部分分配为数组元素。因此,$sections
包含在;
上分割的每个部分。可以使用${sections[0]}
来访问单个部分,其中0
是索引。
上面的awk技巧之所以有效,是因为它是awk中的一个用例或约定。
另一种技术是使用空行分隔记录。根据特殊规定,作为RS值的空字符串表示记录由一行或多行空行分隔。当RS设置为空字符串时,每条记录总是在遇到的第一个空行结束。
假设正好有两个部分,这个非常简单的Perl技巧将打印标准输出,直到遇到空行,然后剩余部分出错;
perl -ne 'if (1../^$/) { print STDOUT } else { print STDERR }'
例如。cat tmp0|perl-ne'if(1../^$/({print STDOUT}else{print STDERR}'>tmp1 2>tmp2
tmp1:
This is a file
with some text
tmp2:
and some more text