How can I extract a predetermined range of lines from a text file on Unix?
我有一个大约23000行的SQL转储文件,其中包含几个数据库的数据。我需要提取此文件的某个部分(即单个数据库的数据),并将其放在新文件中。我知道我想要的数据的起始和结束行号。
有人知道一个unix命令(或一系列命令)从文件中提取16224到16482行之间的所有行,然后将它们重定向到一个新文件中吗?
1 | sed -n '16224,16482p;16483q' filename > newfile |
从SED手册:
p -
Print out the pattern space (to the standard output). This command is usually only used in conjunction with the -n command-line option.n -
If auto-print is not disabled, print the pattern space, then, regardless, replace the pattern space with the next line of input. If
there is no more input then sed exits without processing any more
commands.q -
Exitsed without processing any more commands or input.
Note that the current pattern space is printed if auto-print is not disabled with the -n option.
和
Addresses in a sed script can be in any of the following forms:
number
Specifying a line number will match only that line in the input.An address range can be specified by specifying two addresses
separated by a comma (,). An address range matches lines starting from
where the first address matches, and continues until the second
address matches (inclusively).
1 | sed -n '16224,16482 p' orig-data-file > new-file |
其中1622416482是起始行号和结束行号(包括首尾行号)。这是一个索引。
使用头/尾相当简单:
1 | head -16482 in.sql | tail -258 > out.sql |
使用SED:
1 | sed -n '16482,16482p' in.sql > out.sql |
使用AWK:
1 | awk 'NR>=10&&NR<=20' in.sql > out.sql |
您可以使用"vi",然后使用以下命令:
1 | :16224,16482w!/tmp/some-file |
可选地:
1 | cat file | head -n 16482 | tail -n 258 |
编辑:只需添加解释,使用head-n 16482显示前16482行,然后使用tail-n 258从第一个输出中获取最后258行。
对于
1 | awk 'NR==16224, NR==16482' file |
如果文件很大,那么在读取最后一行之后,它对
1 | awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file |
1 | perl -ne 'print if 16224..16482' file.txt > new_file.txt |
1 2 3 | # print section of file based on line numbers sed -n '16224 ,16482p' # method 1 sed '16224,16482!d' # method 2 |
1 | cat dump.txt | head -16224 | tail -258 |
应该有技巧。这种方法的缺点是,您需要执行算术来确定tail的参数,并考虑是否希望"between"包括结束行。
我正准备发布头尾戏法,但实际上我可能只会启动Emacs。;-)
打开新的输出文件ctl-y节约
让我看看发生了什么。
快速和肮脏:
1 | head -16428 < file.in | tail -259 > file.out |
也许不是最好的方法,但它应该有效。
btw:259=16482-16224+1。
我写了一个名为splitter的haskell程序,它可以做到这一点:阅读我的发布博客文章。
您可以使用以下程序:
1 | $ cat somefile | splitter 16224-16482 |
这就是一切。您需要Haskell来安装它。公正:
1 | $ cabal install splitter |
你就完了。我希望你觉得这个程序有用。
站在Boxxar的肩膀上,我喜欢这样:
1 | sed -n '<first line>,$p;<last line>q' input |
例如
1 | sed -n '16224,$p;16482q' input |
我喜欢这个变体,因为我不需要指定两次结束行号。我测量过使用
即使我们可以这样做来检查命令行:
1 | cat filename|sed 'n1,n2!d' > abc.txt |
例如:
1 | cat foo.pl|sed '100,200!d' > abc.txt |
使用红宝石:
1 | ruby -ne 'puts"#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf |
我会用:
1 | awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt |
fnr包含从文件中读取的行的记录(行)号。
我编写了一个小的bash脚本,您可以从命令行运行它,只要您更新您的路径以包含它的目录(或者您可以将它放在已经包含在路径中的目录中)。
用法:$pinch文件名开始行结束行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #!/bin/bash # Display line number ranges of a file to the terminal. # Usage: $ pinch filename start-line end-line # By Evan J. Coon FILENAME=$1 START=$2 END=$3 ERROR="[PINCH ERROR]" # Check that the number of arguments is 3 if [ $# -lt 3 ]; then echo"$ERROR Need three arguments: Filename Start-line End-line" exit 1 fi # Check that the file exists. if [ ! -f"$FILENAME" ]; then echo -e"$ERROR File does not exist. \t$FILENAME" exit 1 fi # Check that start-line is not greater than end-line if ["$START" -gt"$END" ]; then echo -e"$ERROR Start line is greater than End line." exit 1 fi # Check that start-line is positive. if ["$START" -lt 0 ]; then echo -e"$ERROR Start line is less than 0." exit 1 fi # Check that end-line is positive. if ["$END" -lt 0 ]; then echo -e"$ERROR End line is less than 0." exit 1 fi NUMOFLINES=$(wc -l <"$FILENAME") # Check that end-line is not greater than the number of lines in the file. if ["$END" -gt"$NUMOFLINES" ]; then echo -e"$ERROR End line is greater than number of lines in file." exit 1 fi # The distance from the end of the file to end-line ENDDIFF=$(( NUMOFLINES - END )) # For larger files, this will run more quickly. If the distance from the # end of the file to the end-line is less than the distance from the # start of the file to the start-line, then start pinching from the # bottom as opposed to the top. if ["$START" -lt"$ENDDIFF" ]; then <"$FILENAME" head -n $END | tail -n +$START else <"$FILENAME" tail -n +$START | head -n $(( END-START+1 )) fi # Success exit 0 |
这可能适用于您(GNU SED):
1 | sed -ne '16224,16482w newfile' -e '16482q' file |
或者利用bash:
1 2 | sed -n $'16224,16482w newfile 16482q' file |
我想用一个变量在脚本中做同样的事情,并通过在$variable周围加引号来实现,将变量名与p分开:
1 | sed -n"$first","$count"p imagelist.txt >"$imageblock" |
我想把一个列表分成不同的文件夹,找到初始问题并回答一个有用的步骤。(split命令在旧操作系统上不是一个选项,我必须将代码移植到)。
接受答案中的-n有效。这是另一种方式,以防你有兴趣。
1 | cat $filename | sed"${linenum}p;d"; |
执行以下操作:
因为我们讨论的是从文本文件中提取文本行,所以我将给出一个特殊的例子,在这个例子中,您希望提取与某个模式匹配的所有行。
1 2 3 4 5 6 7 8 9 | myfile content: ===================== line1 not needed line2 also discarded [Data] first data line second data line ===================== sed -n '/Data/,$p' myfile |
将打印[数据]行和其余行。如果要将文本从第1行转换为模式,请键入:sed-n'1,/data/p'myfile。此外,如果您知道两个模式(最好在文本中是唯一的),则可以使用匹配项指定范围的开始行和结束行。
1 | sed -n '/BEGIN_MARK/,/END_MARK/p' myfile |
我认为这可能是一个有用的解决方案。如果表名为"person",则可以使用sed获取恢复表所需的所有行。
1 | sed -n -e '/DROP TABLE IF EXISTS.*`person `/,/UNLOCK TABLES/p' data.sql > new_data.sql |
基于此答案,如果您要还原的表缺少"drop table if exists",则需要在使用新文件之前从该文件底部删除几行以防止删除下一个表。
详细信息也可以在这里找到