我有一个~23000行的SQL转储,其中包含几个数据库的数据价值。我需要提取这个文件的某个部分(即单个数据库的数据),并将其放在一个新文件中。我知道我想要的数据的开始行号和结束行号。

谁知道一个Unix命令(或一系列命令)可以从文件中提取16224到16482行之间的所有行,然后将它们重定向到一个新文件中?


当前回答

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 - Exit sed 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.

and

sed脚本中的地址可以是以下任何一种形式: 数量 指定行号将只匹配输入中的该行。 一个地址范围可以通过指定两个地址来指定 用逗号(,)分隔。地址范围匹配从 第一个地址匹配,并一直持续到第二个 地址匹配(包括)。

其他回答

接受答案中的-n起作用。如果你有兴趣的话,还有另一种方法。

cat $filename | sed "${linenum}p;d";

它的作用如下:

管道插入文件的内容(或根据需要输入文本)。 Sed选择给定的行,打印它 D必须删除行,否则sed将假定最终打印所有行。也就是说,如果没有d,你将得到被选中行打印的所有行打印两次,因为你有${linenum}p部分要求打印它。我很确定-n和这里的d是一样的。

您可以使用'vi',然后使用以下命令:

:16224,16482w!/tmp/some-file

另外:

cat file | head -n 16482 | tail -n 258

编辑:-只是补充解释,您使用head -n 16482显示前16482行,然后使用tail -n 258显示第一次输出的最后258行。

站在拳击手的肩膀上,我喜欢这样:

sed -n '<first line>,$p;<last line>q' input

e.g.

sed -n '16224,$p;16482q' input

$表示“最后一行”,因此第一个命令使sed打印从第16224行开始的所有行,第二个命令使sed在打印第16428行之后退出。(在boxxar的解决方案中,为q范围添加1似乎没有必要。)

我喜欢这个变体,因为我不需要两次指定结束行号。而且我认为使用$不会对性能产生不利影响。

我会用:

awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt

FNR包含从文件中读取的行的记录(行)号。

我编写了一个小型bash脚本,您可以从命令行运行它,只要您更新PATH以包含它的目录(或者您可以将它放在PATH中已经包含的目录中)。

用法:$ pinch filename起始行结束行

#!/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. \n\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