Как извлечь заданный диапазон строк из текстового файла в Unix?

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

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

21 ответов


sed -n '16224,16482p;16483q' filename > newfile

С руководство sed:

p - Распечатайте пространство шаблона (до стандартного вывода). Эта команда обычно используется только в сочетании с параметром-N в командной строке.

n - Если автоматическая печать не отключена, распечатайте пространство шаблона, а затем, независимо от этого, замените пространство шаблона следующей строкой ввода. Если больше нет входа, затем sed выходит без обработки больше команды.

q - Выход sed без обработки каких-либо команд или ввода. Обратите внимание, что текущее пространство шаблона печатается, если автоматическая печать не отключена с параметром-n.

и

адреса в скрипте sed могут быть в любой из следующих форм:

Указание номера строки будет соответствовать только этой строке на входе.

An диапазон адресов можно задать, указав два адреса разделенных запятой (,). Диапазон адресов соответствует строкам, начиная с где первый адрес совпадает, и продолжается до второй адрес совпадает (включительно).


sed -n '16224,16482 p' orig-data-file > new-file

где 16224,16482-номер начальной строки и номер конечной строки включительно. Это 1-индексированные. -n подавляет Эхо ввода как вывода, который вы явно не хотите; цифры указывают диапазон строк, чтобы заставить следующую команду работать; команда p выводит соответствующие строки.


довольно просто с помощью головы / хвоста:

head -16482 in.sql | tail -258 > out.sql

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

sed -n '16482,16482p' in.sql > out.sql

С помощью awk:

awk 'NR>=10&&NR<=20' in.sql > out.sql

вы можете использовать 'vi' , а затем следующую команду:

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

кроме того:

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

EDIT: - просто чтобы добавить объяснение, вы используете голова-n 16482 для отображения первых 16482 строк используйте хвост-n 258 чтобы получить последние 258 строк из первого вывода.


есть другой подход с awk:

awk 'NR==16224, NR==16482' file

если файл огромен, это может быть хорошо для exit после прочтения последней нужной строки. Таким образом, он не будет излишне читать файл до конца:

awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file

perl -ne 'print if 16224..16482' file.txt > new_file.txt

 # print section of file based on line numbers
 sed -n '16224 ,16482p'               # method 1
 sed '16224,16482!d'                 # method 2

sed -n '16224,16482p' < dump.sql


cat dump.txt | head -16224 | tail -258

следует сделать трюк. Недостатком этого подхода является то, что вам нужно выполнить арифметику, чтобы определить аргумент для tail и учесть, хотите ли вы, чтобы "между" включало конечную строку или нет.


быстрый и грязный:

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

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

BTW: 259 = 16482-16224+1.


Я собирался опубликовать трюк с головой / хвостом, но на самом деле я бы, вероятно, просто запустил emacs. ;-)

  1. esc-x goto-line ret 16224
  2. выбрать (ctrl-пробел)
  3. esc-x goto-line ret 16482
  4. esc-w

открыть новый выходной файл, ctl-y save

давайте посмотрим, что происходит.


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

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

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


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

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

$ cat somefile | splitter 16224-16482

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

$ cabal install splitter

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


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

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

Например:

cat foo.pl|sed '100,200!d' > abc.txt

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

ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf

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

использование: $ pinch filename start-line end-line

#!/bin/bash
# Display line number ranges of a file to the terminal.
# Usage: $ pinch filename start-line end-line
# By Evan J. Coon

FILENAME=
START=
END=

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

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

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

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

sed -n $'16224,16482w newfile\n16482q' file

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

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

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


the-n в работе accept answers. Вот еще один способ, если ты не против.

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

Это:

  1. труба в содержимом файла (или корма в тексте, как вы хотите).
  2. sed выбирает заданную строку, печатает ее
  3. d требуется для удаления строк, иначе sed будет считать, что все строки в конечном итоге будут напечатаны. т. е. без d вы получите все строки, напечатанные выбранной строкой, напечатанной дважды, потому что у вас есть часть ${linenum}p, требующая ее печати. Я уверен, что-n в основном делает то же самое, что и d здесь.

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

myfile content:
=====================
line1 not needed
line2 also discarded
[Data]
first data line
second data line
=====================
sed -n '/Data/,$p' myfile

напечатает строку [Data] и оставшуюся. Если вам нужен текст из строки 1 в шаблон, введите: sed-n '1,/Data/p' myfile. Кроме того, если вы знаете два шаблона (лучше быть уникальным в вашем тексте), как начало, так и конец диапазона могут быть указаны с помощью спички.

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

Я думаю, это может быть полезным решением. Если имя таблицы "person", вы можете использовать sed, чтобы получить все строки, необходимые для восстановления таблицы.

sed -n -e '/DROP TABLE IF EXISTS.*`person `/,/UNLOCK TABLES/p' data.sql  > new_data.sql

на основе ответ, где отсутствует "DROP TABLE IF EXIST" для восстанавливаемой таблицы, и вам нужно удалить несколько строк из нижней части нового файла, прежде чем использовать его, чтобы предотвратить удаление следующей таблицы.

подробную информацию также можно найти здесь