获取shell中多次出现的文本

时间:2016-08-02 05:03:22

标签: linux shell

我有一个类似的文件:

航向-1

abc

DEF

GHI

END

航向-2

UVW

XYZ

END

现在,我希望每次出现时HEADING-和END之间的所有文本。我怎样才能做到这一点?我尝试使用grep和sed,但它仅用于单次出现。我想在每个HEADING-和END出现的单独文件中输出此输出

2 个答案:

答案 0 :(得分:0)

这会将HEADING-to-END的每次出现写入单独的文件:

$ awk '/HEADING/{f="file" ++i} /HEADING/,/END/{print>f}' file

运行上面的示例数据后,目录中将有两个新文件:

$ cat file1
HEADING-1
abc
def
ghi
END

$ cat file2
HEADING-2
uvw
xyz
END

如何运作

  • /HEADING/{f="file" ++i}

    每次我们到达包含HEADING的行时,都会更新变量f以包含新文件名。

  • /HEADING/,/END/{print>f}

    对于以HEADING开头且以END结尾的行范围内的任何行,都会将该行写入文件f

变化:排除HEADING和END行

对代码稍作修改,除了省略HEADING和END行外,我们可以写相同的内容:

$ awk '/END/{f=""} f{print>f} /HEADING/{f="file" ++i}' file
$ cat file1
abc
def
ghi
$ cat file2
uvw
xyz

答案 1 :(得分:0)

有很多方法可以解决这个问题。如果您只想将每个HEADING*END之间的文字行分隔成单独的文件,(例如file_000.txt, file_001.txt, ...,您只需使用while循环并使用expr检查每一行的内容,并跳过,增加文件计数,或将行写入当前filecnt编号的文件。例如:

#!/bin/sh

fn="${1:-/dev/stdin}"   ## input filename (or stdin, default)

[ -r "$1" ] || {        ## check that file is readable
    printf "error: file not readable '%s'\n" "$fn"
    exit 1
}

declare -i filecnt=0    ## counter for file number

while IFS= read -r line; do  ## read each line
    if [ $(expr "$line" : "HEADING.*") -gt 0 ]  ## skip if HEADING*
    then
        continue
    elif [ $(expr "$line" : "END.*") -gt 0 ]    ## skip + inc filecnt on END
    then
        ((filecnt++))
        continue
    elif [ $(expr length "$line") -gt 0 ]       ## test non-blank line
    then
        printf -v ofn "file_%03d.txt" "$filecnt"  ## set output file name
        printf "$line\n" >> "$ofn"                ## write line to file name
    fi
done <"$fn"

输入文件

$ cat dat/he.txt
HEADING-1

abc

def

ghi

END

HEADING-2

uvw

xyz

END

示例使用/输出文件

$ sh hdg2end.sh dat/he.txt

$ cat file_000.txt
abc
def
ghi

$ cat file_001.txt
uvw
xyz

仔细看看,如果您有任何疑问,请告诉我。 (注意:根据您的read版本,您可能有也可能没有-r选项 - 如果没有,请忽略它)