Автор Гілка: Видалення newlines з виводу програми  (Прочитано 2948 раз)

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Добрий день (точніше ніч... :), шановне панство...
Потрібно прибрати з виводу програми символи нової строки. Причому зробити це в потоковому режимі, тобто без затримки як в tr. При цьому треба змінювати шматки фраз, тому я намагався це зробити sed-ом.
Але втілити це в життя мені не вдалося. Усілякі \n, \x0A і т.д. він ігнорує, навіть з флагом M до команди s, який, нібито, повинен його переводити в режим multiline. Те ж саме стосується команд y та d.
Звичайно можна написати фільтр на Сі, але оскільки я розробляю невеличку скриптову бібліотечку, хотілося б усе вирішити за допомогою стандартних методів.
Буду вдячний за пропозиції.

Відсутній nickat

  • Письменник
  • *****
  • дописів: 587
  • Карма: +0/-0
  • Debian user
Re: Видалення newlines з виводу програми
« Відповідей #1 : 2006-05-04 12:49:30 »
sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlinesзнайдено в THE SED FAQ.

P.S.: Це була перша відповідь Google на "sed delete newline".
Best regards,
nickat

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3749
  • Карма: +9/-0
  • Програміст
Re: Видалення newlines з виводу програми
« Відповідей #2 : 2006-05-04 12:59:24 »
Якщо потрібно робити фільтрацію без буферизації то боюсь що без примітивного фільтру на Сі тут ніяк не обійтися. Принаймні я написав для себе такий для перекодовування з cp1251 в koi8-u нальоту (для того щоб караоке в cp1251 в консолі під timidity нормально показувалося :-) )...

Я думаю що примітивний код на Сі вирішить вашу проблему:

#include <stdio.h>

int main(int argc, char** argv)
{
  int chr;
  while( (chr=getchar())!=EOF )
  {
    if(chr!='\n')
    {
      putchar(chr);
    }
  }
  return 0;
}

[vlisivka@apollo 20]$ gcc remove-newlines.c -o remove-newlines
[vlisivka@apollo 20]$ ./remove-newlines <remove-newlines.c
#include <stdio.h>int main(int argc, char** argv){  int chr;  while( (chr=getchar())!=EOF )  {    if(chr!='\n')    {      putchar(chr);    }  }  return 0;}[vlisivka@apollo 20]$
[Fedora Linux]

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Видалення newlines з виводу програми
« Відповідей #3 : 2006-05-04 15:08:36 »
2nickat:
Oh, shame on me... Як я міг забути про Гугль?!.. :)
Але все ж таки, ця команда спочатку зчитує увесь ввід до останньої строки, а потім вже видаляє \n. Тому тут та ж проблема що й з tr.
Але тут можна ще дещо поміркувати... Треба якось примусити sed вивести будь-що без кінцевого \n.

Ну, а якщо нічого не виміркується, то зроблю фільтр... Або передивлюсь саму ідею...

Дякую.

Відсутній nickat

  • Письменник
  • *****
  • дописів: 587
  • Карма: +0/-0
  • Debian user
Re: Видалення newlines з виводу програми
« Відповідей #4 : 2006-05-05 16:28:03 »
2nickat:
Треба якось примусити sed вивести будь-що без кінцевого \n.

Якщо автори все того ж THE SED FAQ не помиляються, то це не можливо
Цитата
If the last line of the file contains a newline, GNU sed will add that newline to the output but delete all others, whereas tr will delete all newlines.

2nickat:
Ну, а якщо нічого не виміркується, то зроблю фільтр... Або передивлюсь саму ідею...

А чим не влаштовує варіант від Володимира Лісівки?
Best regards,
nickat

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Видалення newlines з виводу програми
« Відповідей #5 : 2006-05-09 17:22:49 »
Є!
Знайшов.

Одне з застосувань - індикатор прогресу виконання команд:
# початок коду
#! /bin/bash

is_pipe_clean()
{
        for ipc_index in ${PIPESTATUS
  • } ; do

                (( ipc_index )) && return 1
        done
        return 0
}

echo 'Extracting:'
echo -n ' [ '
tar -xjvf /usr/src/Packages/Misc/db-*.tar.bz2 | \
tee logs/db-extract.log | \
sed -n  -e 's/^.*$/echo -n "#" 1>\&2/' \
        -e '71~70 s/^.*$/echo -n -e " ]\n [ #" 1>\&2/' \
        -e 'e' -
if is_pipe_clean ; then
        echo -e ' ]\nSucceed.'
else
        echo -e '* ]\nError!'
fi
# кінець коду
Цей метод, щоправда, використовує аж два GNU extensions...

Чому я не хочу додавати будь-які бінарні програми? Бо це скриптова бібліотека, і я хочу залишити її такою.

P.S. Слухайте, що за дивна поведінка |сode||/code|? Я вважав, що між ними текст ніяк не змінюється... А у мене всі пробіли на початку строки перейшли в... "\n" :). Чи це у мене links глючить?..
« Змінено: 2006-05-09 17:48:28 від ISBear »

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Видалення newlines з виводу програми
« Відповідей #6 : 2006-05-10 00:03:03 »
А ось це:
# початок коду
sed -n  -e 's/^.*$/%/
H
x
s/\n//g
/.\{70\}/b NWLN
x
b OUT
:NWLN
s/^\(.\?\).*$/ ]\\n [ \1/
:OUT
s/^.*$/echo -n -e "&" 1>\&2/
e' -
# кінець коду
дозволяє позбутися принаймні одної залежності від розширень ГНУ. :)

Відсутній Михайло Даниленко

  • Адміністратор ЩОДО
  • Літератор
  • *****
  • дописів: 1262
  • Карма: +0/-0
  • [Debian Stretch]
Re: Видалення newlines з виводу програми
« Відповідей #7 : 2006-05-10 18:17:17 »
А цей варіант по-перше не залежить від будь-яких розширень, а по-друге набагато швидше:
# початок коду
awk -- '
BEGIN {
        ln_cnt=0
        ors_sv=ORS
        ORS=""
        print " < "
        ORS="="
}
{
        out_ln=""
        if ( ++ln_cnt > 70 ) {
                ln_cnt=1
                out_ln=" >\n < "
        }
        print out_ln
}
END {
        ORS=ors_sv
        print " >"
}
' -
# кінець коду

P.S. Ох же ж, мабуть, я всім набрид зі своїми викладками... Але нічого не можу із собою зробити.