У меня есть дамп SQL ~ 23000 строк, содержащий несколько данных на базе данных. Мне нужно извлечь определенный раздел этого файла (т.е. Данные для одной базы данных) и поместить его в новый файл. Я знаю как начальную, так и конечную строки данных, которые я хочу.
Кто-нибудь знает команду Unix (или ряд команд), чтобы извлечь все строки из файла между строкой 16224 и 16482 и затем перенаправить их в новый файл?
sed -n '16224,16482p;16483q' filename > newfile
Из руководства sed:
p - Распечатайте пространство шаблона (до стандартного вывода). Эта команда обычно используется только в сочетании с параметром командной строки -n.
n - Если автоматическая печать не отключена, распечатайте пространство шаблонов, а затем, независимо от того, замените пространство шаблонов на следующую строку ввода. Если ввода больше нет, то sed выходит без обработки каких-либо команд.
q - Выйти из
sed
без обработки каких-либо команд или ввода. Обратите внимание, что текущее пространство шаблонов печатается, если автоматическая печать не отключена с помощью опции -n.
Адреса в сценарии sed могут быть в любой из следующих форм:
number Указание номера строки будет соответствовать только этой строке на входе.
Диапазон адресов можно указать, указав два адреса, разделенных запятой (,). Диапазон адресов соответствует строкам, начинающимся с того, где совпадает первый адрес, и продолжается до второго совпадения (включительно).
sed -n '16224,16482 p' orig-data-file > new-file
Где 16224,16482 - номер стартовой линии и номер конечной линии, включительно. Это 1-индекс. -n
подавляет эхо ввода как выход, чего вы явно не хотите; номера указывают диапазон линий, чтобы включить следующую команду; команда p
выводит соответствующие строки.
sed -n '16224,16482p;16482q' orig-data-file > new-file
что остановка в конце диапазона может быть выполнена с помощью: sed -n '16224,16482p;16482q' orig-data-file > new-file
.
Довольно просто использовать head/tail:
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
tail
.
sed -n 16224,16482p' in.sql >out.sql
а команда awk должна быть awk 'NR>=16224&&NR<=16482' in.sql > out.sql
Вы можете использовать "vi", а затем следующую команду:
:16224,16482w!/tmp/some-file
Альтернативно:
cat file | head -n 16482 | tail -n 258
EDIT: - Чтобы добавить объяснение, вы используете head -n 16482 для отображения первых 16482 строк, затем используйте tail -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
должен сделать трюк. Недостатком этого подхода является то, что вам необходимо выполнить арифметику, чтобы определить аргумент для хвоста и учесть, хотите ли вы, чтобы "между" включал конечную строку или нет.
cat
; head
может читать файл напрямую. Это медленнее, чем многие альтернативы, потому что он использует 2 (3, как показано) команды, где 1 достаточно.
| tail -$((16482 - 16224))
.
Быстрая и грязная:
head -16428 < file.in | tail -259 > file.out
Вероятно, это не лучший способ сделать это, но он должен работать.
BTW: 259 = 16482-16224 + 1.
Использование ruby:
ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf
Даже мы можем это сделать, чтобы проверить в командной строке:
cat filename|sed 'n1,n2!d' > abc.txt
Пример:
cat foo.pl|sed '100,200!d' > abc.txt
cat
ни в одном из них; sed
отлично способен читать файлы самостоятельно, или вы можете перенаправить стандартный ввод из файла.
Я написал программу Haskell под названием splitter, которая делает именно это: прочитайте мой пост в блоге.
Вы можете использовать программу следующим образом:
$ cat somefile | splitter 16224-16482
И это все, что есть. Вам понадобится Haskell, чтобы установить его. Просто:
$ cabal install splitter
И все готово. Я надеюсь, что вы найдете эту программу полезной.
splitter
читает только со стандартного ввода? В некотором смысле это не имеет значения; команда cat
является излишней, делает это или нет. Либо используйте splitter 16224-16482 < somefile
либо (если он принимает аргументы имени файла) splitter 16224-16482 somefile
.
Я бы использовал:
awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt
FNR содержит номер записи (строки) строки, считанной из файла.
Я собирался опубликовать трюк с головой/хвостом, но на самом деле я, вероятно, просто запустил emacs.; -)
открыть новый выходной файл, ctl-y сохранить
Позвольте мне посмотреть, что происходит.
Я хотел сделать то же самое из script с помощью переменной и достигнуть ее, поставив кавычки вокруг переменной $, чтобы отделить имя переменной от p:
sed -n "$first","$count"p imagelist.txt >"$imageblock"
Я хотел разбить список на отдельные папки и найти начальный вопрос и ответить на полезный шаг. (команда split не является опцией на старых os, я должен передать код).
Это может сработать для вас (GNU sed):
sed -ne '16224,16482w newfile' -e '16482q' file
или используя bash:
sed -n $'16224,16482w newfile\n16482q' file
Я написал небольшой bash script, который можно запустить из командной строки, пока вы обновляете свой 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
wc
, которая тратит пропускную способность диска, особенно на гигабайтные файлы. Во всех отношениях это хорошо документировано, но это также излишнее инженерное решение.
Поскольку мы говорим об извлечении строк текста из текстового файла, я дам специальный случай, когда вы хотите извлечь все строки, соответствующие определенному шаблону.
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
В ответах-ответа принимается -n. Здесь другой способ, если вы склонны.
cat $filename | sed "${linenum}p;d";
Это делает следующее:
cat file | sed
лучше записать как sed file
Я думаю, что это может быть полезным решением. Если имя таблицы "человек", вы можете использовать sed для получения всех строк, необходимых для восстановления таблицы.
sed -n -e '/DROP TABLE IF EXISTS.*`person `/,/UNLOCK TABLES/p' data.sql > new_data.sql
Основываясь на этом ответе, в котором отсутствует таблица "DROP TABLE IF EXIST" для таблицы, которую вы восстанавливаете, и вам нужно удалить несколько строк со дна перед тем как использовать его, чтобы предотвратить удаление следующей таблицы.
Подробную информацию также можно найти здесь