Друкуйте непарні рядки, друкуйте парні рядки


18

Я хочу надрукувати з файлів непарні і парні рядки.

Я знайшов цей скрипт оболонки, який використовує ехо.

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

Але хіба немає способу зробити це в один рядок?

Так, я використовую awk, я читав.

Рядові числа:

awk 'NR % 2' filename

рядки з непарними номерами:

awk 'NR % 2 == 1' filename

Але це не працює для мене. Обидва дають однаковий вихід, відповідно до відмінностей. Якщо порівнювати з оригінальним файлом, вони обоє дійсно наполовину довші, і вони містять рядки з непарними номерами. Я щось роблю не так?


6
Перший повинен бути NR % 2 == 0, інакше він еквівалентний другому.
enzotib

Здається, в Інтернеті є декілька документів (включаючи цей), які відображаються у верхній частині пошуку, де зазначено, що NR% 2 дає вам парні рядки, що є нечислими, що невірно, це дає вам непарність, оскільки 1% 2 = 1 = вірно, 2% 2 = 0 = хибно.
дельтарай

Відповіді:


12

Як ви запитали "в один рядок":

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

Зауважте, що більша частина коду пов'язана з вибором вашого фантазійного виводу файлу. В іншому випадку наступного коду буде достатньо для розміщення непарних рядків у "рядок-1" і парні рядки в "рядку-0":

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

26

Я вважаю за краще бути сумісним з POSIX, коли це можливо, тому я подумав, що опублікую цей альтернативний метод. Я часто їх використовую для того, щоб обробляти текст перед xargsконвеєрами.

Роздрукуйте навіть нумеровані рядки,

sed -n 'n;p'

Роздрукувати непарні нумеровані рядки,

sed -n 'p;n'

Хоча я часто використовую awk, це надмірний рівень для такого типу завдань.


14

Це легко:

 sed -n 2~2p filename

буде друкувати парні рядки з імені файлу

sed -n 1~2p filename

друкуватиме непарні рядки.


1
+1, для стороннього використання AWK. Не POSIX sed, але це все-таки солідний метод.
Дж. М. Бекер

@TechZilla Я не розумію "використання AWK сторонньо" - awk також POSIX.
jw013

3
@ jw013: Нічого не в чому awk, особисто я цим дуже часто користуюся. Я ніколи не говорив, що щось awkстосується "Not POSIX" , я мав на увазі sedваріанти відповіді. Зокрема, ~оператора, це розширення GNU, яке все ще прийнятно для багатьох людей. Щодо "використання AWK сторонньо , I personally believe using awk" для цього простого завдання є зайвим. Тож +1 було для виконання завдання sedлегшою утилітою, ніж awk.
Дж. М. Бекер

1
Чи можете мені хтось пояснити, як працює тут ~ оператор?
Forever Learner

9

Для парних чисел повинен бути код

awk 'NR%2==0' filename

& для непарних чисел

awk 'NR%2==1' filename

1
цей ідеальний. Навіть працює, якщо вам потрібно отримати рядки з кроком 10, скажімо, що вам потрібно зменшити впорядкований файл розміром від 1 мільйона до 100 к. Це саме те, що я хотів.
Декстер

Як можна друкувати парні стовпці в AWK? Я не можу це працювати gawk 'FS=",";NF%2==0' file.csv.
hhh

2

Ви можете це зробити одним sedвикликом, не потрібно читати файл двічі:

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

або, якщо ви віддаєте перевагу в одному рядку:

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

Зауважте, що вони не дадуть очікуваного результату, якщо файл містить лише один рядок (рядок буде wобрано evenзамість того, oddяк перший nне виконується). Щоб уникнути цього, додайте умову:

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

Як це працює ? Ну, він використовує три sedкоманди:
n- якщо не в останньому рядку, надрукуйте пробіл шаблону до stdout(який перенаправлений на файл odd), замініть його на наступний рядок (так що тепер він обробляє рівний рядок) і продовжуйте виконувати інші команди
w- додайте простір шаблону, який потрібно подати even
d- видалити поточний простір шаблону та перезапустити цикл - побічний ефект цього полягає в тому sed, що ніколи не буде автоматично надруковано простір шаблону, як ніколи не доходить до кінця сценарію

Іншими словами, nвиконується тільки на непарних рядках і wі dвиконуються тільки на парних лініях. sedніколи не потрапляє до автодруку, якщо, як я вже сказав, вхід складається з одного рядка.


Ви можете, будь ласка, розібратися, як це працює?
Forever Learner

Велике спасибі don_crissti за вашу допомогу. Щиро ціную це, також прихильне.
Forever Learner

0

Спробуйте це:

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

Ви впевнені у виведенні номерів записів?
манатура

вибачте з цього приводу, я змінив його для виведення цілих рядків.
renma

0

Я б поїхав, perlтому що мені подобається perl:

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

Використовує той факт, що -pнеявно друкує, для реплікації того, як це sedпрацює, - і ми використовуємо selectдля вибору ручки файлу, до якого він пише.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.