Lihat melalui file dan cetak teks dari baris tertentu

8

Saya memiliki file dengan data yang saya simpan. Sekarang saya ingin mencetak hasil saya ke file baru.

Sebagai contoh, mari kita ambil contoh ini randomlog.log:

Link encap:Ethernet HWaddr 08:00:00:00:00:67
inet addr:10.10.10.10 Bcast:10.10.10.10 Mask:255.255.255.0
inet6 addr: fe80::casf:sdfg:23ra:dg12/64 Scope:Link

Bagaimana saya bisa hanya mengambil data dari karakter ke-12 hingga ke-20 dari baris pertama dan kemudian karakter ke-4 hingga ke-8 dari baris ke-3? Output akan terlihat seperti ini:

Ethernet
t6 ad

Apakah ini mungkin? Saya ingin mengatur garis dan dari posisi ke posisi ini.

Insanebench420
sumber

Jawaban:

9

Inilah sedpendekatannya:

$ sed -nE '1s/.{11}(.{8}).*/\1/p; 3s/.{3}(.{4}).*/\1/p' file  
Ethernet
t6 a

Penjelasan

The -nMenekan output normal (normal adalah untuk mencetak setiap baris input) sehingga hanya mencetak ketika diberitahu untuk. The -Ememungkinkan ekspresi reguler diperpanjang.

The sedScript memiliki dua perintah, baik menggunakan operator substitusi ( s/original/replacement/). Hanya 1s/.{11}(.{8}).*/\1/pakan berjalan pada baris 1 (itulah yang 1sdilakukan), dan akan cocok dengan 11 karakter 1 baris ( .{11}), kemudian menangkap 8 berikutnya ( (.{8}), tanda kurung adalah "grup tangkap") dan kemudian semuanya sampai akhir baris ( .*). Semua ini diganti dengan apa pun yang ada di kelompok tangkap ( \1; jika ada kelompok tangkap kedua, itu akan menjadi \2dll.). Akhirnya, ppada bagian akhir ( s/foo/bar/p) menyebabkan garis untuk dicetak setelah substitusi dibuat. Ini menghasilkan hanya 8 karakter target yang dihasilkan.

Perintah kedua adalah ide umum yang sama kecuali bahwa itu hanya akan berjalan pada baris ke-3 ( 3s) dan akan membuat 4 karakter dimulai dari ke-4.


Anda juga dapat melakukan hal yang sama dengan perl:

$ perl -ne 'if($.==1){s/.{11}(.{8}).*/\1/}
            elsif($.==3){s/.{3}(.{4}).*/\1/}
            else{next}; print; ' file 
Ethernet
t6 a

Penjelasan

The -neberarti "membaca file baris masukan demi baris dan menerapkan script yang diberikan oleh -emasing-masing baris. Script adalah ide dasar yang sama seperti sebelumnya. The $.variabel memegang nomor baris saat ini sehingga kami memeriksa apakah nomor baris adalah baik 1atau 3dan, jika jadi, jalankan substitusi, lewati saja. Karena itu printhanya akan dijalankan untuk dua baris karena semua yang lain akan dilewati.


Tentu saja, ini Perl, jadi TIMTOWTDI :

$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file 
Ethernet 
t6 a

Penjelasan

Di sini, -aberarti "pisahkan setiap baris input pada karakter yang diberikan oleh -Fdan simpan sebagai array @F. Karena karakter yang diberikan kosong, ini akan menyimpan setiap karakter dari garis input sebagai elemen @F. Kemudian, kita mencetak elemen 11-19 ( array mulai menghitung pada 0) untuk baris pertama dan 3-7 untuk baris ketiga.

terdon
sumber
1

pendekatan awk:

$ awk 'NR==1{print substr($0,12,8)};NR==3{print substr($0,4,4)}' input.txt  
Ethernet
t6 a

Penggunaan NRuntuk menentukan nomor baris (dalam terminologi awk - catatan), dan dengan demikian mencetak substring dari baris tersebut. substr()fungsi dalam format

substr(string,starting position,how much offset) 

Python

$ python -c 'import sys                                                                                                                                                
> for index,line in enumerate(sys.stdin,1):                                                                                                                            
>     if index == 1:
>          print line[11:19]
>     if index == 3:
>          print line[3:7]' < input.txt
Ethernet
t6 a

Ini menggunakan <operator shell untuk mengalihkan aliran input ke proses python dari file input. Perhatikan bahwa string dalam python diindeks 0, oleh karena itu Anda perlu menggeser nomor karakter yang Anda inginkan semua dengan 1.

cara shell portabel

Ini bekerja di ksh, dash, bash. Hanya mengandalkan utilitas shell, bukan eksternal.

#!/bin/sh

rsubstr(){
    i=0;
    while [ $i -lt  $2 ];
    do
        rmcount="${rmcount}?"
        i=$(($i+1))
    done;
    echo "${1#$rmcount}"
}

lsubstr(){
    printf "%.${2}s\n" "$1"
}

line_handler(){
    case $2 in
        1) lsubstr "$(rsubstr "$1" 11)" 8 ;;
        3) lsubstr "$(rsubstr "$1" 3)" 5 ;;
    esac
}

readlines(){
    line_count=1
    while IFS= read -r line;
    do
        line_handler "$line" "$line_count"
        line_count=$(($line_count+1))
    done < $1
}

readlines "$1"

Dan itu berfungsi seperti ini:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad
Sergiy Kolodyazhnyy
sumber