在双换行符上Bash拆分文件



我有一些文件的内容随着文件的不同而变化。每个文件有两段行,由一个空行分隔。我永远不知道这两个部分有多少行或字符。

该文件可能看起来像这样。

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

最新更新