我有一个类似的文件:
航向-1
abc
DEF
GHI
END
航向-2
UVW
XYZ
END
现在,我希望每次出现时HEADING-和END之间的所有文本。我怎样才能做到这一点?我尝试使用grep和sed,但它仅用于单次出现。我想在每个HEADING-和END出现的单独文件中输出此输出
答案 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行外,我们可以写相同的内容:
$ 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
选项 - 如果没有,请忽略它)