pengembangan-web-mp-pd.com

Bagaimana saya bisa mengekstrak rentang garis yang telah ditentukan dari file teks di Unix?

Saya memiliki ~ 23000 baris SQL dump yang berisi beberapa data bernilai data. Saya perlu mengekstrak bagian tertentu dari file ini (mis. Data untuk satu basis data) dan menempatkannya di file baru. Saya tahu nomor awal dan akhir dari data yang saya inginkan.

Adakah yang tahu perintah Unix (atau serangkaian perintah) untuk mengekstrak semua baris dari file antara say line 16224 dan 16482 lalu mengarahkannya ke file baru?

447
Adam J. Forster
sed -n '16224,16482p;16483q' filename > newfile

Dari manual sed :

p - Cetak ruang pola (ke output standar). Perintah ini biasanya hanya digunakan bersama dengan opsi -n command-line.

n - Jika cetak-otomatis tidak dinonaktifkan, cetak ruang pola, lalu, ganti, ganti ruang pola dengan baris input berikutnya. Jika tidak ada lagi input kemudian sed keluar tanpa memproses lagi perintah.

q - Keluar sed tanpa memproses lagi perintah atau input . Perhatikan bahwa ruang pola saat ini dicetak jika cetak-otomatis tidak dinonaktifkan dengan opsi -n.

dan

Alamat dalam skrip sed dapat berupa salah satu dari bentuk berikut:

angka Menentukan nomor baris hanya akan cocok dengan baris itu di input.

Rentang alamat dapat ditentukan dengan menetapkan dua alamat dipisahkan oleh koma (,). Rentang alamat cocok dengan garis mulai dari di mana alamat pertama cocok, dan berlanjut sampai yang kedua. alamat cocok (secara inklusif).

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

Di mana 16224.16482 adalah nomor baris awal dan nomor baris akhir, inklusif. Ini 1-diindeks. -n menekan gema input sebagai output, yang Anda jelas tidak inginkan; angka menunjukkan rentang garis untuk membuat perintah berikut beroperasi; perintah p mencetak baris yang relevan.

195
JXG

Cukup sederhana menggunakan kepala/ekor:

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

menggunakan sed:

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

menggunakan awk:

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

Anda bisa menggunakan 'vi' dan kemudian perintah berikut:

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

Kalau tidak: 

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

Sunting: - Hanya untuk menambahkan penjelasan, Anda menggunakan head -n 16482 untuk menampilkan 16482 baris pertama kemudian gunakan tail -n 258 untuk mendapatkan 258 baris terakhir dari output pertama. 

25
Mark Janssen

Ada pendekatan lain dengan awk:

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

Jika file berukuran besar, sebaiknya exit setelah membaca baris yang diinginkan terakhir. Dengan cara ini tidak perlu membaca file sampai selesai:

awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file
20
fedorqui
Perl -ne 'print if 16224..16482' file.txt > new_file.txt
14
mmaibaum
 # print section of file based on line numbers
 sed -n '16224 ,16482p'               # method 1
 sed '16224,16482!d'                 # method 2
8
Cetra

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

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

harus melakukan trik. Kelemahan dari pendekatan ini adalah bahwa Anda perlu melakukan aritmatika untuk menentukan argumen untuk tail dan untuk memperhitungkan apakah Anda ingin 'antara' menyertakan garis akhir atau tidak.

5
JP Lodine

Cepat dan kotor:

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

Mungkin bukan cara terbaik untuk melakukannya tetapi harus berhasil.

BTW: 259 = 16482-16224 + 1.

3
jan.vdbergh

Saya baru akan memposting trik kepala/ekor, tetapi sebenarnya saya mungkin baru saja menjalankan emacs. ;-)

  1. esc-x goto-line ret 16224
  2. tandai (ctrl-space)
  3. esc-x goto-line ret 16482
  4. esc-w

buka file output baru, simpan ctl-y

Mari saya lihat apa yang terjadi.

3
sammyo

Bahkan kita dapat melakukan ini untuk memeriksa di baris perintah:

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

Sebagai contoh:

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

Menggunakan Ruby:

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

Saya akan menggunakan:

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

FNR berisi nomor catatan (baris) dari baris yang sedang dibaca dari file.

2
Paddy3118

Saya menulis sebuah program Haskell bernama splitter yang melakukan hal ini: punya baca posting blog rilis saya .

Anda dapat menggunakan program ini sebagai berikut:

$ cat somefile | splitter 16224-16482

Dan hanya itu yang ada di sana. Anda akan membutuhkan Haskell untuk menginstalnya. Hanya:

$ cabal install splitter

Dan kamu sudah selesai. Saya harap Anda menemukan program ini bermanfaat.

2
Robert Massaioli

Ini mungkin bekerja untuk Anda (sed GNU):

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

atau memanfaatkan bash:

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

Saya menulis skrip bash kecil yang dapat Anda jalankan dari baris perintah, asalkan Anda memperbarui PATH Anda untuk memasukkan direktori (atau Anda dapat menempatkannya di direktori yang sudah terkandung dalam PATH).

Penggunaan: $ 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
1
Nerdfighter

Saya ingin melakukan hal yang sama dari skrip menggunakan variabel dan mencapainya dengan meletakkan tanda kutip di sekitar variabel $ untuk memisahkan nama variabel dari p:

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

Saya ingin membagi daftar menjadi folder yang terpisah dan menemukan pertanyaan awal dan menjawab langkah yang bermanfaat. (perintah split bukan opsi pada os lama saya harus port kode ke).

1
KevinY

Karena kita berbicara tentang mengekstraksi baris teks dari file teks, saya akan memberikan kasus khusus di mana Anda ingin mengekstraksi semua baris yang cocok dengan pola tertentu. 

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

Akan mencetak baris [Data] dan sisanya. Jika Anda ingin teks dari line1 ke pola, Anda mengetik: sed -n '1,/Data/p' myfile. Selanjutnya, jika Anda tahu dua pola (lebih baik menjadi unik dalam teks Anda), baik garis awal dan akhir rentang dapat ditentukan dengan kecocokan.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile
0
Kemin Zhou

Berdiri di pundak boxxar, saya suka ini:

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

misalnya.

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

$ berarti "baris terakhir", jadi perintah pertama membuat sed mencetak semua baris yang dimulai dengan baris 16224 dan perintah kedua membuat sed berhenti setelah garis pencetakan 16428 (Menambahkan 1 untuk rentang q- dalam solusi boxxar sepertinya tidak diperlukan.)

Saya suka varian ini karena saya tidak perlu menentukan nomor baris akhir dua kali. Dan saya mengukur bahwa menggunakan $ tidak memiliki efek yang merugikan pada kinerja.

0
Tilman Vogel

-N pada jawaban terima berfungsi. Berikut cara lain jika Anda ingin.

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

Ini melakukan hal berikut:

  1. pipa dalam isi file (atau umpan dalam teks sesuka Anda).
  2. sed memilih garis yang diberikan, mencetaknya
  3. d diharuskan untuk menghapus baris, jika tidak maka akan menganggap semua baris pada akhirnya akan dicetak. yaitu, tanpa huruf d, Anda akan mendapatkan semua garis yang dicetak oleh garis yang dipilih dicetak dua kali karena Anda memiliki bagian $ {linenum} p yang meminta untuk dicetak. Saya cukup yakin -n pada dasarnya melakukan hal yang sama dengan d di sini.
0
ThinkBonobo