我希望能够将一个文本文件拆分为两个文件,这样如果文件中存在该模式,则第一个输出将包含给定模式之前的所有行(但不包括该模式),如果不存在该模式,则第一个输出将包含整个输入文件。第二个文件应该是模式之后的所有行或空文件。
file1.txt:
a
b
c
$ split.sh 文件1.txt "b"
file1.txt.before:
a
file1.txt.after:
c
$ split.sh file1.txt "d"
file1.txt.before:
a
b
c
file1.txt.after:
我尝试了不同的 sed 命令,我想到最接近的方法是:
sed "1,/$2/!d" < $1 > $1.before
sed "1,/$2/d" < $1 > $1.after
但这存在一些问题: - 之前的文件缺少输入文件的第一行 - 之前的文件包含模式
答案1
使用拆分对于这样的事情。
CSPLIT(1) User Commands CSPLIT(1)
NAME
csplit - split a file into sections determined by context lines
-f, --prefix=PREFIX
use PREFIX instead of 'xx'
--suppress-matched
suppress the lines matching PATTERN
关于命令的正则表达式部分:
Each PATTERN may be:
INTEGER
copy up to but not including specified line number
/REGEXP/[OFFSET]
copy up to but not including a matching line
%REGEXP%[OFFSET]
skip to, but not including a matching line
{INTEGER}
repeat the previous pattern specified number of times
{*} repeat the previous pattern as many times as possible
A line OFFSET is a required '+' or '-' followed by a positive integer.
命令
csplit <file.txt> /<string>/ '{*}'
<file.txt>
将根据查找的频率将其拆分为多个部分<string>
。'{*}'
将重复搜索并为每个出现创建多个文件。默认情况下,文件将被命名为xx{number}
;使用--prefix
选项可以更改它。添加--suppress-matched
将从文件中省略搜索字符串。
答案2
以下是使用 Awk 的一种方法:
awk -v pattern='^b' '
NR==1 {suff = ".before"} $0 ~ pattern {suff = ".after"; next} {print > FILENAME suff}
' file1.txt
前任。
awk -v pattern='^b' 'NR==1 {suff = ".before"} $0 ~ pattern {suff = ".after"; next} {print > FILENAME suff}' file1.txt
给予
$ head file1.txt*
==> file1.txt <==
a
b
c
==> file1.txt.after <==
c
==> file1.txt.before <==
a