【问题标题】:How to extract the lines between patterns?如何提取图案之间的线条?
【发布时间】:2011-10-29 14:27:14
【问题描述】:

我有一个格式如下的文件:

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

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

[PATTERN]
line1
line2
line3
.
.
.
line

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

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

Shell 脚本如何做到这一点?

【问题讨论】:

标签: bash shell scripting sed grep


【解决方案1】:

这假设你使用 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 命令。

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

【讨论】:

  • 解决方案是正确的.. 但是我们可以直接使用 sed 或 awk 或 grep 之类的东西吗?
【解决方案2】:

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

#!/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[*]}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多