如何提取模式之间的界限?

时间:2011-08-18 08:50:07

标签: bash shell scripting sed grep

我的文件格式如下:

[PATTERN]
line1
line2
line3
.
.
.
line
[PATTERN]
line1
line2
line3
.
.
.
line
[PATTERN]
line1
line2
line3
.
.
.
line

我想从上面的文件中提取以下块:

[PATTERN]
line1
line2
line3
.
.
.
line
  

注意:2 [PATTERN]之间的行数可能会有所不同,因此不能依赖行数。

     

基本上,我想将每个模式及其后面的行存储到数据库中,因此我必须在我的文件中迭代所有这些块。

如何使用Shell Scripting?

2 个答案:

答案 0 :(得分:2)

这假设您使用bash作为shell。对于其他shell,实际的解决方案可能不同。

假设您的数据位于data

i=0 ; cat data  | while read line ; do \
  if [ "$line" == "[PATTERN]" ] ; then \
    i=$(($i + 1)) ; touch file.$i ; continue ; \
  fi ; echo "$line" >> file.$i ; \
done

按实际分隔模式更改[PATTERN]

这将创建文件file.1file.2

编辑:回应有关awk解决方案的请求:

awk '/^\[PATTERN\]$/{close("file"f);f++;next}{print $0 > "file"f}' data

想法是每次找到[PATTERN]时跳过一个新文件(跳过该行 - next命令),并将所有连续行写入该文件。如果您需要在生成的文件中包含[PATTERN],请删除next命令。

注意[]的转义,它们对正则表达式有特殊意义。如果您的模式不包含这些模式,则不需要转义。 ^$是可取的,因为它们会将您的模式与您通常需要的行的开头和结尾联系起来。

答案 1 :(得分:0)

这肯定可以改进,但是如果你想在一个数组中存储行,这是我过去所做的事情:

#!/bin/bash
file=$1
gp_cnt=-1
i=-1

while read line
do
  # Match pattern
  if [[ "$line" == "[PATTERN]" ]]; then
    let "gp_cnt +=1"
    # If this is not the first match process group
    if [[ $gp_cnt -gt 0 ]]; then
      # Process the group
      echo "Processing group #`expr $gp_cnt - 1`"
      echo ${parsed[*]}
    fi
    # Start new group
    echo "Pattern #$gp_cnt catched"
    i=0
    unset parsed
    parsed[$i]="$line"

    # Other lines (lines before first pattern are not processed)
  elif [[ $gp_cnt != -1 ]]; then
    let "i +=1"
    parsed[$i]="$line"
  fi
done < <(cat $file)

# Process last group
echo "Processing group #$gp_cnt"
echo ${parsed[*]}

我不喜欢最后一组处理循环...