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

unix command-line sed text-processing

410568 просмотра

22 ответа

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

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

Автор: Adam J. Forster Источник Размещён: 17.05.2019 03:06

Ответы (22)


677 плюса

Решение
sed -n '16224,16482p;16483q' filename > newfile

Из руководства пользователя sed :

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

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

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

а также

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

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

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

Автор: boxxar Размещён: 17.09.2008 01:42

192 плюса

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

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

Автор: JXG Размещён: 17.09.2008 01:46

78 плюса

Довольно просто, используя голову / хвост:

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
Автор: manveru Размещён: 17.09.2008 01:46

25 плюса

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

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

В качестве альтернативы:

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

РЕДАКТИРОВАТЬ: - Просто чтобы добавить объяснение, вы используете head -n 16482 для отображения первых 16482 строк, а затем с помощью tail -n 258, чтобы получить последние 258 строк из первого вывода.

Автор: Mark Janssen Размещён: 17.09.2008 01:42

20 плюса

Есть еще один подход с awk:

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

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

awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file
Автор: fedorqui Размещён: 14.01.2014 04:30

13 плюса

perl -ne 'print if 16224..16482' file.txt > new_file.txt
Автор: mmaibaum Размещён: 17.09.2008 01:43

8 плюса

 # print section of file based on line numbers
 sed -n '16224 ,16482p'               # method 1
 sed '16224,16482!d'                 # method 2
Автор: Cetra Размещён: 17.09.2008 01:42

5 плюса

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

Автор: cubex Размещён: 17.09.2008 01:45

5 плюса

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

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

Автор: JP Lodine Размещён: 17.09.2008 01:49

3 плюса

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

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

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

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

Автор: jan.vdbergh Размещён: 17.09.2008 01:44

2 плюса

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

  1. esc- xGoto-Line ret16224
  2. отметка ( ctrl- space)
  3. esc- xGoto-Line ret16482
  4. esc-w

откройте новый выходной файл, ctl-y сохраните

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

Автор: sammyo Размещён: 17.09.2008 01:49

2 плюса

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

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

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

Автор: Paddy3118 Размещён: 01.01.2013 06:51

2 плюса

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

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

$ cat somefile | splitter 16224-16482

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

$ cabal install splitter

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

Автор: Robert Massaioli Размещён: 25.07.2013 10:43

2 плюса

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

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

Например:

cat foo.pl|sed '100,200!d' > abc.txt
Автор: Chinmoy Padhi Размещён: 05.02.2014 06:41

2 плюса

Используя ruby:

ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
Автор: Carl Blakeley Размещён: 21.05.2015 12:23

1 плюс

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

Использование: $ 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=$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
Автор: Nerdfighter Размещён: 10.12.2014 05:06

1 плюс

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

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

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

sed -n $'16224,16482w newfile\n16482q' file
Автор: potong Размещён: 10.08.2015 01:00

1 плюс

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

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

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

Автор: KevinY Размещён: 28.10.2017 09:35

0 плюса

Работа с ключами -n в ответах. Вот другой способ, если вы склонны.

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

Это делает следующее:

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

0 плюса

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

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
Автор: Kemin Zhou Размещён: 14.02.2018 10:52

0 плюса

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

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

например

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

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

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

Автор: Tilman Vogel Размещён: 14.02.2019 01:52

-3 плюса

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

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

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

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

Автор: dvergur Размещён: 06.10.2016 03:20
Вопросы из категории :
32x32