Как я могу извлечь заранее определенный диапазон строк из текстового файла в Unix? - PullRequest
470 голосов
/ 17 сентября 2008

У меня есть дамп SQL из ~ 23000 строк, содержащий данные из нескольких баз данных. Мне нужно извлечь определенный раздел этого файла (то есть данные для одной базы данных) и поместить его в новый файл. Я знаю номера начала и конца строки нужных мне данных.

Кто-нибудь знает команду Unix (или серию команд), чтобы извлечь все строки из файла, скажем, между строками 16224 и 16482, а затем перенаправить их в новый файл?

Ответы [ 22 ]

3 голосов
/ 17 сентября 2008

Быстро и грязно:

head -16428 < file.in | tail -259 > file.out

Возможно, это не лучший способ сделать это, но он должен работать.

Кстати: 259 = 16482-16224 + 1.

3 голосов
/ 14 февраля 2019

Стоя на плечах boxxar, мне нравится это:

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

, например

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

$ означает «последняя строка», поэтому первая команда заставляет sed печатать все строки, начинающиеся со строки 16224, а вторая команда sed выходит после печатать строку 16428. (Добавление 1 для q -диапазона в решении boxxar, по-видимому, не является необходимым.)

Мне нравится этот вариант, потому что мне не нужно указывать номер конечной строки дважды. И я измерил, что использование $ не оказывает негативного влияния на производительность.

3 голосов
/ 26 июля 2013

Я написал программу на Haskell под названием splitter , которая делает именно это: прочитайте в моем посте .

Вы можете использовать программу следующим образом:

$ cat somefile | splitter 16224-16482

И это все, что есть. Вам понадобится Haskell для его установки. Просто:

$ cabal install splitter

И все готово. Я надеюсь, что вы найдете эту программу полезной.

3 голосов
/ 21 мая 2015

Использование ruby:

ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
3 голосов
/ 05 февраля 2014

Даже мы можем сделать это, чтобы проверить в командной строке:

cat filename|sed 'n1,n2!d' > abc.txt

Например:

cat foo.pl|sed '100,200!d' > abc.txt
2 голосов
/ 01 января 2013

Я бы использовал:

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

FNR содержит номер записи (строки) строки, считываемой из файла.

1 голос
/ 28 октября 2017

Я хотел сделать то же самое из скрипта, использующего переменную, и достиг этого, поставив кавычки вокруг переменной $, чтобы отделить имя переменной от p:

sed -n "$first","$count"p imagelist.txt >"$imageblock"

Я хотел разбить список на отдельные папки, нашел начальный вопрос и ответил на полезный шаг. (команда split не является опцией для старой ОС, на которую я должен перенести код).

1 голос
/ 10 августа 2015

Это может сработать для вас (GNU sed):

sed -ne '16224,16482w newfile' -e '16482q' file

или воспользоваться bash:

sed -n $'16224,16482w newfile\n16482q' file
1 голос
/ 10 декабря 2014

Я написал небольшой bash-скрипт, который можно запустить из командной строки, при условии, что вы обновляете свой PATH, чтобы включить его каталог (или вы можете поместить его в каталог, который уже содержится в PATH).

Использование: $ pinch, имя файла, начало строки, конец строки

#!/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
0 голосов
/ 15 февраля 2018

Поскольку речь идет об извлечении строк текста из текстового файла, я приведу особый случай, когда вы хотите извлечь все строки, которые соответствуют определенному шаблону.

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. Кроме того, если вы знаете два шаблона (лучше быть уникальными в вашем тексте), начальная и конечная линии диапазона могут быть указаны с совпадениями.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile
...