Cetak garis bernomor ganjil, cetak garis genap

18

Saya ingin mencetak baris bernomor ganjil dan genap dari file.

Saya menemukan skrip shell yang menggunakan gema.

#!/bin/bash
# Write a shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------

file=$1
counter=0

eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name

if [ $# -eq 0 ]
then
    echo "$(basename $0) file"
    exit 1
fi

if [ ! -f $file ]
then
    echo "$file not a file"
    exit 2
fi

while read line
do
    # find out odd or even line number
    isEvenNo=$( expr $counter % 2 )

    if [ $isEvenNo -ne 0 ]
    then
        # even match
        echo $line >> $eout
    else
        # odd match
        echo $line >> $oout
    fi
    # increase counter by 1
    (( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"

Tetapi apakah tidak ada cara untuk melakukannya dalam satu baris?

Ya, gunakan awk, saya baca.

Baris genap:

awk 'NR % 2' filename

garis ganjil:

awk 'NR % 2 == 1' filename

Tetapi itu tidak berhasil untuk saya. Keduanya menghasilkan output yang sama, menurut diff. Jika dibandingkan dengan file asli, mereka berdua memang setengah panjang, dan mereka berdua berisi baris bernomor ganjil. Apakah saya melakukan sesuatu yang salah?

ixtmixilix
sumber
6
Yang pertama seharusnya NR % 2 == 0, kalau tidak setara dengan yang kedua.
enzotib
Tampaknya ada beberapa dokumen daring (termasuk yang ini) yang muncul di bagian atas pencarian yang menyatakan bahwa NR% 2 memberi Anda garis bernomor genap, yang tidak benar, memberi Anda yang aneh karena 1% 2 = 1 = benar, 2% 2 = 0 = salah.
deltaray

Jawaban:

12

Saat Anda bertanya "dalam satu baris":

awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename

Perhatikan bahwa sebagian besar kode disebabkan oleh pilihan nama file keluaran mewah Anda. Kalau tidak, kode berikut akan cukup untuk menempatkan garis ganjil di "line-1" dan bahkan garis di "line-0":

awk '{print>"line-"NR%2}' filename
manatwork
sumber
26

Saya lebih suka POSIX yang kompatibel, jika memungkinkan, jadi saya pikir saya akan memposting metode alternatif ini. Saya sering menggunakan ini untuk memotong teks, sebelum xargssaluran pipa.

Cetak Garis Bernomor,

sed -n 'n;p'

Cetak Garis Ganjil,

sed -n 'p;n'

Meskipun saya sering menggunakan awk, itu berlebihan untuk jenis tugas ini.

JM Becker
sumber
14

Itu mudah:

 sed -n 2~2p filename

akan mencetak garis bernomor genap dari nama file

sed -n 1~2p filename

akan mencetak garis bernomor ganjil.

neuron34
sumber
1
+1, karena tidak menggunakan AWK secara eksternal. Tidak POSIX sed, tapi itu masih metode yang solid.
JM Becker
@ TechZilla Saya tidak mengerti "menggunakan AWK secara eksternal" - awk juga POSIX.
jw013
3
@ jw013: Tidak ada yang salah dengan awk, secara pribadi saya sangat sering menggunakannya. Saya tidak pernah mengatakan sesuatu tentang 'Bukan POSIX' awk, saya merujuk pada opsi jawaban sed. Khususnya ~operator, ini adalah ekstensi GNU, yang masih dapat diterima oleh banyak orang. Mengenai 'menggunakan AWK secara luar , I personally believe using biasa' untuk tugas sederhana ini terlalu banyak. Jadi +1 adalah untuk menyelesaikan tugas dengan sed, utilitas yang lebih ringan daripada awk.
JM Becker
1
Bisakah seseorang tolong jelaskan bagaimana ~ operator bekerja di sini?
Forever Learner
9

Untuk angka genap kode harus

awk 'NR%2==0' filename

& untuk angka ganjil

awk 'NR%2==1' filename
Neel
sumber
1
ini sempurna. Bahkan berfungsi jika Anda perlu mendapatkan baris dengan penambahan 10, katakan Anda harus mengurangi file yang dipesan berukuran 1 juta hingga 100 ribu. Inilah yang saya inginkan.
Dexter
Bagaimana Anda bisa mencetak kolom bernomor genap di AWK? Saya tidak bisa mendapatkan ini berfungsi gawk 'FS=",";NF%2==0' file.csv.
hhh
2

Anda dapat melakukannya dengan satu sedpermohonan, tidak perlu membaca file dua kali:

sed '$!n
w even
d' infile > odd

atau, jika Anda lebih suka dalam satu baris:

sed -e '$!n' -e 'w even' -e d infile > odd

Perhatikan bahwa ini tidak akan memberikan hasil yang diharapkan jika file hanya berisi satu baris (baris akan ditulis wulang evenbukan oddsebagai yang pertama ntidak dieksekusi). Untuk menghindarinya, tambahkan syarat:

sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd

Bagaimana itu bekerja ? Nah, ini menggunakan tiga sedperintah:
n- jika tidak pada baris terakhir cetak ruang pola ke stdout(yang diarahkan ke file odd), ganti dengan baris berikutnya (jadi sekarang sedang memproses garis genap) dan terus menjalankan perintah yang tersisa
w- tambahkan ruang pola untuk file even
d- hapus ruang pola saat ini dan mulai ulang siklus - efek sampingnya adalah sedtidak akan pernah mencetak ruang pola secara otomatis karena tidak pernah mencapai akhir skrip

Dengan kata lain, ndieksekusi hanya pada garis ganjil dan wdan ddieksekusi hanya pada garis genap. sedtidak pernah mendapatkan autoprint kecuali, seperti yang saya katakan, input terdiri dari satu baris.

don_crissti
sumber
bisa tolong jelaskan bagaimana cara kerjanya?
Forever Learner
Terima kasih banyak, don_crissti atas bantuan Anda. Hormatilah itu, dibesarkan juga.
Forever Learner
0

Coba ini:

awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename
renma
sumber
Apakah Anda yakin tentang mengeluarkan nomor rekaman?
manatwork
maaf tentang itu, saya memodifikasinya untuk menampilkan seluruh baris.
renma
0

Saya akan pergi perlkarena saya suka perl:

perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'

Menggunakan fakta yang -psecara implisit mencetak, untuk mereplikasi cara sedkerjanya - dan kami gunakan selectuntuk memilih file yang ditangani.

Sobrique
sumber