In các dòng số lẻ, in các dòng số chẵn


18

Tôi muốn in các dòng số lẻ và số chẵn từ các tệp.

Tôi tìm thấy kịch bản shell này sử dụng tiếng vang.

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

Nhưng không có cách nào để làm điều đó trong một dòng?

Vâng, sử dụng awk, tôi đọc.

Các dòng số chẵn:

awk 'NR % 2' filename

các dòng số lẻ:

awk 'NR % 2 == 1' filename

Nhưng nó không làm việc cho tôi. Cả hai sản xuất cùng một đầu ra, theo diff. Khi so sánh với tệp gốc, cả hai đều thực sự dài bằng một nửa và cả hai đều chứa các dòng số lẻ. Tôi có làm điều gì sai?


6
Cái đầu tiên nên NR % 2 == 0, nếu không nó tương đương với cái thứ hai.
enzotib

Dường như có một số tài liệu trực tuyến (bao gồm cả tài liệu này) xuất hiện ở đầu tìm kiếm cho biết NR% 2 cung cấp cho bạn các dòng được đánh số chẵn, không chính xác, nó cung cấp cho bạn số lẻ vì 1% 2 = 1 = đúng, 2% 2 = 0 = sai.
deltaray

Câu trả lời:


12

Như bạn đã hỏi, trong một dòng.

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

Lưu ý rằng hầu hết các mã là do lựa chọn tên tệp đầu ra ưa thích của bạn. Nếu không thì đoạn mã sau sẽ đủ để đặt các dòng lẻ trong dòng Line-1 và dòng chẵn trong dòng Line-0 -

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

26

Tôi thích tương thích POSIX, bất cứ khi nào có thể, vì vậy tôi nghĩ tôi sẽ đăng phương pháp thay thế này. Tôi thường sử dụng chúng để đọc văn bản, trước các xargsđường ống.

In các dòng được đánh số chẵn

sed -n 'n;p'

In các dòng được đánh số lẻ,

sed -n 'p;n'

Mặc dù tôi thường sử dụng awk, nhưng nó quá mức cho loại nhiệm vụ này.


14

Điều đó thật dễ dàng:

 sed -n 2~2p filename

sẽ in các dòng được đánh số chẵn từ tên tệp

sed -n 1~2p filename

sẽ in các dòng số lẻ.


1
+1, vì không sử dụng AWK bên ngoài. Không phải POSIX sed, nhưng nó vẫn là phương pháp vững chắc.
JM Becker

@TechZilla Tôi không hiểu "sử dụng AWK một cách bất thường" - awk cũng là POSIX.
jw013

3
@ jw013: Không có gì sai awk, cá nhân tôi sử dụng nó rất thường xuyên. Tôi chưa bao giờ nói bất cứ điều gì là 'Không phải POSIX' awk, tôi đang đề cập đến các sedlựa chọn của câu trả lời . Cụ thể là ~toán tử, đó là một phần mở rộng GNU, vẫn được nhiều người chấp nhận. Về việc 'sử dụng AWK một cách , I personally believe using vô cùng awk` cho nhiệm vụ đơn giản này là quá mức cần thiết. Vì vậy, +1 là để hoàn thành nhiệm vụ với sed, một tiện ích nhẹ hơn awk.
JM Becker

1
Ai đó có thể vui lòng giải thích làm thế nào ~ nhà điều hành làm việc ở đây?
Học viên mãi mãi

9

Đối với các số chẵn, mã phải là

awk 'NR%2==0' filename

& cho số lẻ

awk 'NR%2==1' filename

1
cái này là hoàn hảo Thậm chí hoạt động nếu bạn cần nhận được các hàng tăng dần 10, giả sử bạn cần giảm một tệp đã đặt hàng có kích thước 1 triệu xuống còn 100k. Đây chính xác là những gì tôi muốn.
Dexter

Làm thế nào bạn có thể in các cột được đánh số chẵn trong AWK? Tôi không thể làm việc này gawk 'FS=",";NF%2==0' file.csv.
hhh

2

Bạn có thể làm điều đó với một lệnh sedgọi duy nhất , không cần phải đọc tệp hai lần:

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

hoặc, nếu bạn thích trong một dòng:

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

Lưu ý rằng những điều này sẽ không mang lại kết quả như mong đợi nếu một tệp chỉ chứa một dòng (dòng sẽ được wchuyển sang eventhay vì oddnhư dòng đầu tiên nkhông được thực thi). Để tránh điều đó, hãy thêm một điều kiện:

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

Làm thế nào nó hoạt động ? Vâng, nó sử dụng ba sedlệnh:
n- nếu không ở dòng cuối cùng in không gian mẫu tới stdout(được chuyển hướng đến tệp odd), thay thế nó bằng dòng tiếp theo (vì vậy bây giờ nó đang xử lý một dòng chẵn) và tiếp tục thực hiện các lệnh còn lại
w- nối thêm không gian mẫu để tập tin even
d- xóa không gian mẫu hiện tại và khởi động lại chu trình - tác dụng phụ của việc này là sedsẽ không bao giờ tự động in không gian mẫu vì nó không bao giờ đến cuối tập lệnh

Nói cách khác, n được thực hiện trên các dòng lẻ wdchỉ được thực hiện trên các dòng chẵn. sedkhông bao giờ được tự động in trừ khi, như tôi đã nói, đầu vào bao gồm một dòng duy nhất.


bạn có thể vui lòng giải thích làm thế nào nó hoạt động?
Học viên mãi mãi

Cảm ơn rất nhiều don_crissti đã giúp đỡ của bạn. Trân trọng đánh giá cao nó, nâng cao là tốt.
Học viên mãi mãi

0

Thử đi:

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

Bạn có chắc chắn về việc xuất các số kỷ lục?
manatwork

xin lỗi về điều đó, tôi đã sửa đổi nó để xuất toàn bộ dòng.
renma

0

Tôi muốn đi cùng perlvì tôi thích perl:

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

Sử dụng thực tế là -pin ngầm, để sao chép cách thức sedhoạt động - và chúng tôi sử dụng selectđể chọn tệp nào xử lý tệp mà nó ghi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.