Tek sayılı satırları, çift numaralı satırları yazdırma


18

Dosyalardan tek sayılı ve çift numaralı satırları yazdırmak istiyorum.

Yankıyı kullanan bu kabuk betiğini buldum.

#!/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"

Ama bunu bir satırda yapmanın bir yolu yok mu?

Evet, awk kullan, okudum.

Çift numaralı çizgiler:

awk 'NR % 2' filename

tek sayılı çizgiler:

awk 'NR % 2 == 1' filename

Ama benim için işe yaramıyor. Her ikisi de dif. Orijinal dosyayla karşılaştırıldığında, ikisi de gerçekten yarı uzunluktadır ve her ikisi de tek sayılı satırları içerir. Yanlış bir şey mi yapıyorum?


6
Birincisi NR % 2 == 0, aksi takdirde ikincisine eşit olmalıdır.
enzotib

Bir aramanın en üstünde, NR% 2'nin size çift sayılı satırları verdiğini belirten, doğru olmayan, size gariplik verdiği için birkaç belge çevrimiçi (bu da dahil olmak üzere) var, çünkü% 1 = 1 = doğru,% 2 2 = 0 = yanlış.
deltaray

Yanıtlar:


12

“Tek satırda” sorduğunuz gibi:

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

Kodun çoğunun, süslü çıktı dosya adı seçiminizden kaynaklandığını unutmayın. Aksi takdirde, “line-1” içine tek satırlar ve hatta “line-0” içine satırlar koymak için aşağıdaki kod yeterli olacaktır:

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

26

POSIX uyumlu olmayı tercih ediyorum, mümkün olduğunda bu alternatif yöntemi yayınlayacağımı düşündüm. Bunları sık sık xargsboru hatlarından önce metin değiştirmek için kullanıyorum .

Çift Numaralı Satırları Yazdır,

sed -n 'n;p'

Tek Numaralı Satırları Yazdır,

sed -n 'p;n'

Sık kullandığım halde awk, bu tür görevler için aşırıya kaçıyor.


14

Bu kolay:

 sed -n 2~2p filename

dosya adından çift numaralı satırlar yazdıracak

sed -n 1~2p filename

tek sayılı çizgiler yazdırır.


1
+1, AWK'yı harici olarak kullanmadığınız için. POSIX sed değil, ama yine de sağlam bir yöntem.
JM Becker

@TechZilla "AWK'yi harici olarak kullanma" anlamıyorum - awk de POSIX.
jw013

3
@ jw013: Hiçbir şey yanlış değil awk, şahsen çok sık kullanıyorum. Asla bir şey hakkında 'POSIX değil' awkdemedim, cevaplayıcının sedseçeneklerinden bahsediyordum . Özellikle ~operatör, birçok insan için hala kabul edilebilir bir GNU uzantısıdır. ' , I personally believe using AWK'yi harici olarak awk kullanma' ile ilgili olarak bu basit görev aşırı derecede. +1, görevi seddaha hafif bir yardımcı programla tamamlamak içindi awk.
JM Becker

1
Birisi operatörün burada nasıl çalıştığını açıklayabilir mi?
Sonsuza Kadar Öğrenen

9

Çift sayılar için kod

awk 'NR%2==0' filename

& tek sayılar için

awk 'NR%2==1' filename

1
bu mükemmel. Hatta 10'luk artışlarla satır almanız gerekiyorsa bile çalışır, 1 milyon dolarlık sipariş edilen dosyayı 100k'ye düşürmeniz gerektiğini söyleyin. Bu tam olarak istediğim şeydi.
Dexter

AWK'de çift sayılı sütunları nasıl yazdırabilirsiniz? Bunu çalıştıramıyorum gawk 'FS=",";NF%2==0' file.csv.
hhh

2

Bunu tek bir sedçağrı ile yapabilirsiniz , dosyayı iki kez okumanıza gerek yok:

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

veya bir satırda tercih ediyorsanız:

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

Bir dosya yalnızca bir satır içeriyorsa bunların beklenen sonucu vermeyeceğini unutmayın ( ilk wyürütme evenyerine satır yeniden oluşturulacaktır ). Bundan kaçınmak için bir koşul ekleyin:oddn

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

Nasıl çalışır ? Üç sedkomut kullanır :
n- son satırda değilse , desen alanını (dosyaya yönlendirilir) olarak yazdırın , bir sonraki satırla değiştirin (böylece şimdi çift bir satırı işliyor) ve kalan komutları yürütmeye devam edin - ekleme dosyalanacak desen alanı - geçerli desen alanını silin ve döngüyü yeniden başlatın - bunun yan etkisi , desen alanını asla komut dosyasının sonuna ulaşmadığı için otomatik olarak yazdırmaz.stdoutodd
weven
dsed

Başka bir deyişle, nsadece tek hat üzerinde çalıştırılır ve wve dsadece hatta satırlarda yürütülür. sedDediğim gibi, girdi tek bir satırdan oluşmadıkça asla otomatik yazdırmaya geçmez.


nasıl çalıştığını lütfen ayrıntılı olarak açıklar mısınız?
Sonsuza Kadar Öğrenen

Yardımınız için çok teşekkürler don_crissti. Saygılarımızla, takdir de.
Sonsuza Kadar Öğrenci

0

Bunu dene:

awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename

Kayıt numaralarının çıktısından emin misiniz?
manatwork

bunun için üzgünüm, tüm satırların çıktısını almak için değiştirdim.
renma

0

Ben gitmek istiyorum perlçünkü perl:

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

-pÖrtük olarak yazdırılan gerçeği kullanır, nasıl sedçalıştığını çoğaltmak için - ve selecthangi dosya tanıtıcısını yazacağını seçmek için kullanırız .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.