Получить часть строки до последнего : (или удалить последний символ в строке) (не используя sed, awk и переменных)

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение sash-kan »

Nazyvaemykh писал(а):
01.09.2011 20:53
Тогда ужь проще использовать временный файл вместо трубки
тема-то, собственно, про pipe, а не про коней в вакууме·
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
liaonau
Сообщения: 390
ОС: gentoo

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение liaonau »

vipe использует временный файл, переоткрывает потоки… Это точно внутри не проще, чем с rev, просто скрыто.
Ну вот, например, еще вариант (тоже, правда, намного хуже чем с rev):

Код: Выделить всё

~ $ echo "1:2:3:4:5\na:b:c:d" | perl -plaF':' -e '$_=join ":",@F[0..@F-2]'
1:2:3:4
a:b:c
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

liaonau писал(а):
02.09.2011 00:48
vipe использует временный файл, переоткрывает потоки… Это точно внутри не проще, чем с rev, просто скрыто.
Ну вот, например, еще вариант (тоже, правда, намного хуже чем с rev):

Код: Выделить всё

~ $ echo "1:2:3:4:5\na:b:c:d" | perl -plaF':' -e '$_=join ":",@F[0..@F-2]'
1:2:3:4
a:b:c
Ого, до каких вариантов добрались. :) Это хуже не только чем rev, но и чем s/:[^:]*$//.

Впрочем, всё это обсуждение давно носит чисто академический характер: статья ещё десять дней назад сдана, а сейчас, возможно, уже и напечатана.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
01.09.2011 16:03
Снова только Ваши эмоции. Я не только не говорил про "не хочешь знать" -- напротив, я сказал явно, что в более подходящем контексте о регулярных выражениях планирую рассказывать.

перечитал тему с начала.
ИМХО, это пример, где НЕ нужно использовать конвейер, и где есть более понятные и простые пути (особенно удобны тут bash-переменные, как здесь: Получить часть строки до последнего : (или удалить последний символ в строке) я-бы так сделал). Если всё-же следовать условию, то получается такое: Получить часть строки до последнего : (или удалить последний символ в строке) Ну или красивые, но явно неэкономичные варианты с rev.
t.t писал(а):
02.09.2011 17:48
Впрочем, всё это обсуждение давно носит чисто академический характер: статья ещё десять дней назад сдана, а сейчас, возможно, уже и напечатана.

придётся прочитать... :-)
Спасибо.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

drBatty писал(а):
15.09.2011 16:28
t.t писал(а):
01.09.2011 16:03
Снова только Ваши эмоции. Я не только не говорил про "не хочешь знать" -- напротив, я сказал явно, что в более подходящем контексте о регулярных выражениях планирую рассказывать.
перечитал тему с начала.
ИМХО, это пример, где НЕ нужно использовать конвейер, и где есть более понятные и простые пути (особенно удобны тут bash-переменные, как здесь: Получить часть строки до последнего : (или удалить последний символ в строке) я-бы так сделал).
Т.е. добавлять в конвейер цикл? На мой взгляд, уж это-то точно некрасивое и невыгодное решение.

drBatty писал(а):
15.09.2011 16:28
Ну или красивые, но явно неэкономичные варианты с rev.
Неэкономичное в каком смысле? По производительности отличия от sed в пределах погрешности.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
16.09.2011 15:34
Т.е. добавлять в конвейер цикл? На мой взгляд, уж это-то точно некрасивое и невыгодное решение.

нет конечно!
ну например Получить часть строки до последнего :

Shell

$ X="a:b:c:d" $ echo ${X%:*} a:b:c


я не предлагаю засовывать ЭТО в конвейер! Но согласитесь - это простое и логичное решение. И если нет ограничений (про конвейер), то я-бы его и использовал.

t.t писал(а):
16.09.2011 15:34
Неэкономичное в каком смысле? По производительности отличия от sed в пределах погрешности.

если строки будут длинными, то sed будет работать намного быстрее.
для sed 's/:[^:]*//' и для строки в N символов вам потребуется прочитать N символов. И всё (ну ещё конечно взять N символов из потока, и отдать M<N символов в поток, но это в любом случае). В случае rev вам потребуется поменять местами N/2 символов, причём, в большинстве случаев - по одному. И потом всё равно просматривать N символов, и ещё менять местами M символов. Если N ~ 10, то конечно это не играет роли, но думаю при N ~ 1000 разница будет в десятки раз.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение sash-kan »

кстати, а ведь можно bash-евую конструкцию и в pipe завернуть·
типа:
$ echo "x:y:z" | read a; echo ${a##*:} | sed 's/^/"/;s/$/"/'
"z"

p.s. формально, это будет уже другая «труба», но об этом можно и (до поры) умолчать…
p.p.s. а вот так это уже и формально будет одна «труба»:
$ echo "x:y:z" | { read a; echo ${a##*:}; } | sed 's/^/"/;s/$/"/'
"z"
но в целях обучения лучше, конечно воздержаться от формализма·
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

sash-kan писал(а):
16.09.2011 20:36
read a; echo ${a

согласен.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5404
ОС: Gentoo

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение /dev/random »

sash-kan писал(а):
16.09.2011 20:36
кстати, а ведь можно bash-евую конструкцию и в pipe завернуть·
типа:
$ echo "x:y:z" | read a; echo ${a##*:} | sed 's/^/"/;s/$/"/'
"z"

А что, это у тебя правда работает? В bash переменные, установленные частями пайпа, "забываются" при выходе из пайпа. echo здесь не увидит переменной a.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

/dev/random писал(а):
16.09.2011 23:40
А что, это у тебя правда работает?

Shell

$ echo "x:y:z" | ( read a; echo ${a##*:} ) z


оно?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

drBatty писал(а):
16.09.2011 16:41
t.t писал(а):
16.09.2011 15:34
Т.е. добавлять в конвейер цикл? На мой взгляд, уж это-то точно некрасивое и невыгодное решение.
нет конечно!
ну например Получить часть строки до последнего :

Shell

$ X="a:b:c:d" $ echo ${X%:*} a:b:c


я не предлагаю засовывать ЭТО в конвейер! Но согласитесь - это простое и логичное решение. И если нет ограничений (про конвейер), то я-бы его и использовал.
Как же нет? Мне ведь нужно было получить часть не от одной строки, а от каждой.

drBatty писал(а):
16.09.2011 16:41
t.t писал(а):
16.09.2011 15:34
Неэкономичное в каком смысле? По производительности отличия от sed в пределах погрешности.
если строки будут длинными, то sed будет работать намного быстрее.
для sed 's/:[^:]*//' и для строки в N символов вам потребуется прочитать N символов. И всё (ну ещё конечно взять N символов из потока, и отдать M<N символов в поток, но это в любом случае). В случае rev вам потребуется поменять местами N/2 символов, причём, в большинстве случаев - по одному. И потом всё равно просматривать N символов, и ещё менять местами M символов. Если N ~ 10, то конечно это не играет роли, но думаю при N ~ 1000 разница будет в десятки раз.

Код: Выделить всё

t $ echo $(seq 1000) | tr -cd '[0-9]' | wc -c
2893
t $ time for s in $(seq 100); do for c in $(seq 1000); do echo -n $c; done | rev | cut -d : -f 2- | rev; done >/dev/null

real    0m10.979s
user    0m8.501s
sys     0m4.276s
t $ time for s in $(seq 100); do for c in $(seq 1000); do echo -n $c; done | sed 's/:[^:]*$//'; done >/dev/null

real    0m10.419s
user    0m8.017s
sys     0m3.732s


drBatty писал(а):
16.09.2011 23:49
/dev/random писал(а):
16.09.2011 23:40
А что, это у тебя правда работает?

Shell

$ echo "x:y:z" | ( read a; echo ${a##*:} ) z


оно?
Здесь выхода из пайпа нет. А без скобок действительно не должно работать.

А, виноват, там ведь двоеточий нет. Вот для чистоты эксперимента:

Код: Выделить всё

t $ time for s in $(seq 100); do for c in $(seq 1000); do echo -n :$c; done | sed 's/:[^:]*$//'; done >/dev/null

real    0m11.093s
user    0m8.805s
sys     0m3.656s
t $ time for s in $(seq 100); do for c in $(seq 1000); do echo -n :$c; done | rev | cut -d : -f 2- | rev; done >/dev/null

real    0m11.384s
user    0m8.645s
sys     0m4.436s
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение sash-kan »

/dev/random писал(а):
16.09.2011 23:40
sash-kan писал(а):
16.09.2011 20:36
кстати, а ведь можно bash-евую конструкцию и в pipe завернуть·
типа:
$ echo "x:y:z" | read a; echo ${a##*:} | sed 's/^/"/;s/$/"/'
"z"

А что, это у тебя правда работает? В bash переменные, установленные частями пайпа, "забываются" при выходе из пайпа. echo здесь не увидит переменной a.
да, видимо, от предыдущего запуска взялась переменная·
но если в «формальном» варианте, то работает:
$ echo "x:y:z" | { read a; echo ${a##*:}; } | sed 's/^/"/;s/$/"/'
"z"
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
17.09.2011 12:38
Как же нет? Мне ведь нужно было получить часть не от одной строки, а от каждой.

вот этого в условии не было :)
t.t писал(а):
17.09.2011 12:38
Здесь выхода из пайпа нет. А без скобок действительно не должно работать.

ну сделайте выход. оно и с выходом будет работать:

Код: Выделить всё

doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} )
z
doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z

t.t писал(а):
17.09.2011 12:38
Вот для чистоты эксперимента:

три канавы копать в три раза дольше. Если у вас получилось "до обеда" - это ни о чём не говорит.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

drBatty писал(а):
17.09.2011 13:30
t.t писал(а):
17.09.2011 12:38
Как же нет? Мне ведь нужно было получить часть не от одной строки, а от каждой.
вот этого в условии не было :)
В условии было, что нужен конвейер. А здесь я только разжевал, почему он нужен.

drBatty писал(а):
17.09.2011 13:30
t.t писал(а):
17.09.2011 12:38
Здесь выхода из пайпа нет. А без скобок действительно не должно работать.
ну сделайте выход. оно и с выходом будет работать:

Код: Выделить всё

doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} )
z
doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z
Здесь нет выхода, здесь по-прежнему есть скобки.

drBatty писал(а):
17.09.2011 13:30
t.t писал(а):
17.09.2011 12:38
Вот для чистоты эксперимента:
три канавы копать в три раза дольше. Если у вас получилось "до обеда" - это ни о чём не говорит.
Я провёл эксперимент в тех условиях, о которых Вы говорили, даже усилил их (почти четыре тысячи символов в строке в окончательном варианте вместо одной тысячи). Этот эксперимент показал ошибочность Вашего утверждения. А Вы вместо признания своей неправоты или ответных практических примеров пытаетесь отписаться общими фразами. Похвально, ничего не скажешь.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение Nazyvaemykh »

Тоже попробовал поизмерять, что и как. Результаты:

Код: Выделить всё

$ for i in `seq 1 10000`; do seq -s ':' 1 200 >> test.file; done
$ time sed 's/:[^:]*$//'  test.file > /dev/null

real    0m1.464s
user    0m1.445s
sys    0m0.010s
$ time rev test.file | cut -f2- -d':' | rev > /dev/null

real    0m0.515s
user    0m0.965s
sys    0m0.028s
$ time sed 's/\(.*\):.*/\1/'  test.file > /dev/null

real    0m3.529s
user    0m3.509s
sys    0m0.013s

$ time grep -o '.*:' test.file  | grep -o '.*[^:]' > /dev/null

real    0m2.925s
user    0m3.651s
sys    0m0.027s
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
19.09.2011 12:57
В условии было, что нужен конвейер. А здесь я только разжевал, почему он нужен.

ну дык

Код: Выделить всё

while read s;
 do echo ${a##*:} >output
done < input

t.t писал(а):
19.09.2011 12:57

Код: Выделить всё

doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z

Здесь нет выхода, здесь по-прежнему есть скобки.

ну и что, что скобки? это внутри конвейера, и это работает. В условии не было "не использовать скобок". Было "без sed/awk". И было "в конвейере". :)
Кстати, такая конструкция во всяком случае не сложнее, чем другие. ИМХО.
t.t писал(а):
19.09.2011 12:57
Этот эксперимент показал ошибочность Вашего утверждения. А Вы вместо признания своей неправоты или ответных практических примеров пытаетесь отписаться общими фразами. Похвально, ничего не скажешь.

виноват, исправлюсь...

Shell

$ time sed 's/:[^:]*$//' cp_u.sql >/dev/null real 0m32.426s user 0m28.009s sys 0m0.213s $ time LC_ALL=C sed 's/:[^:]*$//' cp_u.sql >/dev/null real 0m5.991s user 0m5.721s sys 0m0.114s $ time rev cp_u.sql | cut -d : -f 2- | rev >/dev/null real 0m13.797s user 0m10.277s sys 0m0.900s



Как видно, sed работает 28сек, что куда как медленнее cut (10сек), однако, такой странный результат объясняется просто - sed работает в многобайтовой кодировке, и потому её задача намного сложнее (ей приходится обрабатывать символы с переменным числом байтов). Если отключить UTF-8, то результат полностью согласуется с моей теорией: 5секунд. Что вдвое быстрее rev+cut+rev.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

PS: я правда не учёл, что rev тоже умеет UTF-8, потому результат некорректный.
Но разворачивать в LC_ALL=C у rev почему-то не получается:

Shell

$ export LC_ALL=C $ echo "тест" | rev rev: stdin: Invalid or incomplete multibyte or wide character


Оказывается, решение с rev далеко не универсально - скрипт рухнет, если на входе неправильная последовательность символов, даже при LC_ALL=C...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

кстати, ИМХО задача попросту не имеет и не может иметь никакого решения, кроме как с использованием сторонних утилит (в этом смысле rev - ничем не лучше sed/awk, это ведь не bash). Проблема во второй части задачи "или удалить последний символ в строке": Как можно узнать, что символ последний? Только одним способом - прочитать следующий символ. Однако, нам тогда придётся либо сохранить текущий символ где-то, либо использовать утилиту, которая сохраняет символы/строки. Если первый символ удалить можно, то последний - нет. Последнее двоеточие - тоже нельзя, ибо невозможно узнать, что это последний символ, в момент чтения этого символа.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение Nazyvaemykh »

drBatty попробуйте тогда два grep в LC_ALL=C. Потому что grep на таких регулярках работает существенно быстрее sed'а.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

Nazyvaemykh
ок:

Shell

# ru_RU.UTF-8 $ time grep -o '.*:' cp_u.sql | grep -o '.*[^:]' > /dev/null real 1m9.790s user 0m58.307s sys 0m5.870s $ export LC_ALL=C $ time grep -o '.*:' cp_u.sql | grep -o '.*[^:]' > /dev/null real 0m5.559s user 0m2.710s sys 0m0.645s $ unset LC_ALL $ time grep -o '.*:' cp_u.sql | grep -o '.*[^:]' > /dev/null real 1m8.110s user 0m58.942s sys 0m5.812s



Как видно, grep -o без UTF работает примерно вдвое быстрее sed, но вот с UTF-8 вдвое медленнее.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

drBatty писал(а):
19.09.2011 13:56
t.t писал(а):
19.09.2011 12:57
В условии было, что нужен конвейер. А здесь я только разжевал, почему он нужен.

ну дык

Код: Выделить всё

while read s;
 do echo ${a##*:} >output
done < input
Вы, похоже, уже забыли, с чего мы начали:
drBatty писал(а):
16.09.2011 16:41
t.t писал(а):
16.09.2011 15:34
Т.е. добавлять в конвейер цикл? На мой взгляд, уж это-то точно некрасивое и невыгодное решение.
нет конечно!
ну например Получить часть строки до последнего :

Shell

$ X="a:b:c:d" $ echo ${X%:*} a:b:c


я не предлагаю засовывать ЭТО в конвейер! Но согласитесь - это простое и логичное решение. И если нет ограничений (про конвейер), то я-бы его и использовал.
(;

drBatty писал(а):
19.09.2011 13:56
t.t писал(а):
19.09.2011 12:57

Код: Выделить всё

doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z

Здесь нет выхода, здесь по-прежнему есть скобки.

ну и что, что скобки? это внутри конвейера, и это работает. В условии не было "не использовать скобок". Было "без sed/awk". И было "в конвейере". :)
Кстати, такая конструкция во всяком случае не сложнее, чем другие. ИМХО.
И снова приходится напоминать, с чего начинали:
/dev/random писал(а):
16.09.2011 23:40
sash-kan писал(а):
16.09.2011 20:36
кстати, а ведь можно bash-евую конструкцию и в pipe завернуть·
типа:
$ echo "x:y:z" | read a; echo ${a##*:} | sed 's/^/"/;s/$/"/'
"z"
А что, это у тебя правда работает? В bash переменные, установленные частями пайпа, "забываются" при выходе из пайпа. echo здесь не увидит переменной a.


t.t писал(а):
19.09.2011 12:57

Shell

$ time sed 's/:[^:]*$//' cp_u.sql >/dev/null real 0m32.426s user 0m28.009s sys 0m0.213s $ time LC_ALL=C sed 's/:[^:]*$//' cp_u.sql >/dev/null real 0m5.991s user 0m5.721s sys 0m0.114s $ time rev cp_u.sql | cut -d : -f 2- | rev >/dev/null real 0m13.797s user 0m10.277s sys 0m0.900s



Как видно, sed работает 28сек, что куда как медленнее cut (10сек), однако, такой странный результат объясняется просто - sed работает в многобайтовой кодировке, и потому её задача намного сложнее (ей приходится обрабатывать символы с переменным числом байтов). Если отключить UTF-8, то результат полностью согласуется с моей теорией: 5секунд. Что вдвое быстрее rev+cut+rev.
Любопытно. На содержимое файла можно посмотреть?
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение Nazyvaemykh »

Добавлю свои замеры с awk и vim:

Код: Выделить всё

$ time gawk -F: 'BEGIN{OFS=":"};{NF=NF-1;print}' test.file > /dev/null

real    0m0.757s
user    0m0.714s
sys    0m0.013s
$ time LC_ALL=C gawk -F: 'BEGIN{OFS=":"};{NF=NF-1;print}' test.file > /dev/null

real    0m0.327s
user    0m0.316s
sys    0m0.005s
$ time mawk -F: 'BEGIN{OFS=":"};{NF=NF-1;print}' test.file > /dev/null

real    0m0.346s
user    0m0.337s
sys    0m0.008s
$ time LC_ALL=C nawk -F: 'BEGIN{OFS=":"};{NF=NF-1;print}' test.file > /dev/null

real    0m0.819s
user    0m0.812s
sys    0m0.003s
$ time vim -esn --noplugin -c'1,$normal $F:D' -c 'wq' test.tmp

real    0m0.428s
user    0m0.367s
sys    0m0.048s
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
19.09.2011 15:37
Вы, похоже, уже забыли, с чего мы начали:

я помню. но я так и не понял, зачем вам конвейер, если можно и без него?
t.t писал(а):
19.09.2011 15:37
И снова приходится напоминать, с чего начинали:

А что, это у тебя правда работает? В bash переменные, установленные частями пайпа, "забываются" при выходе из пайпа. echo здесь не увидит переменной a.

так я и предлагаю способ, как исправить этот недостаток данного решения. Что в нём не так? Оно даже работает.
t.t писал(а):
19.09.2011 15:37
Любопытно. На содержимое файла можно посмотреть?

это продукт mysqldump из небольшой БД (38Мб ЕМНИП). там есть русские буквы в UTF-8, английские, и достаточно много двоеточий. Mysqldump засовывает таблицу в 1000 строк в 1..2 строчки. Не знаете зачем?

Nazyvaemykh
ваши тесты недостоверны - слишком быстро.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение Nazyvaemykh »

Нет, не слишком.
Иначе может оказаться недостоверно в другую сторону. Если программа долго запускается, но быстро работает? На больших файлах она получит неоправданное преимущество.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

Nazyvaemykh писал(а):
19.09.2011 19:26
Иначе может оказаться недостоверно в другую сторону. Если программа долго запускается, но быстро работает? На больших файлах она получит неоправданное преимущество.

чему там запускаться-то?!
grep у меня 192К размером. 192КИЛОБАЙТ!
это вам не MS-Office.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

drBatty писал(а):
19.09.2011 19:00
t.t писал(а):
19.09.2011 15:37
Вы, похоже, уже забыли, с чего мы начали:
я помню. но я так и не понял, зачем вам конвейер, если можно и без него?
А я так и не понял, зачем "без него", если "с ним" проще и короче.

drBatty писал(а):
19.09.2011 19:00
t.t писал(а):
19.09.2011 15:37
И снова приходится напоминать, с чего начинали:
А что, это у тебя правда работает? В bash переменные, установленные частями пайпа, "забываются" при выходе из пайпа. echo здесь не увидит переменной a.
так я и предлагаю способ, как исправить этот недостаток данного решения. Что в нём не так? Оно даже работает.
Это был не "недостаток", а банальная техническая ошибка. Параллельно sash-kan привёл и верное решение, которое ничем принципиальным от Вашего не отличается. А вот часть нашего с Вами диалога выше:
drBatty писал(а):
17.09.2011 13:30
t.t писал(а):
17.09.2011 12:38
Здесь выхода из пайпа нет. А без скобок действительно не должно работать.

ну сделайте выход. оно и с выходом будет работать:

Код: Выделить всё

doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} )
z
doc@dt:~$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z
Вы пишете, что здесь выход из пайпа есть, хотя его по-прежнему нет.

drBatty писал(а):
19.09.2011 19:00
t.t писал(а):
19.09.2011 15:37
Любопытно. На содержимое файла можно посмотреть?
это продукт mysqldump из небольшой БД (38Мб ЕМНИП). там есть русские буквы в UTF-8, английские, и достаточно много двоеточий. Mysqldump засовывает таблицу в 1000 строк в 1..2 строчки. Не знаете зачем?
Думаю, явно не для того, чтобы этот дамп обрабатывать текстовыми утилитами. (; Я показал выше, что при почти четырёх тысячах символов в строке разница по времени пренебрежимо мала. А это явно избыточно: в моей задаче и пятисот символов быть не может.

P.S. У меня всё чаще возникает впечатление, что я с ботом разговариваю. В частности, очевидные вещи приходится по четыре раза проговаривать.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение sash-kan »

t.t писал(а):
20.09.2011 11:51
У меня всё чаще возникает впечатление, что я с ботом разговариваю.
так оно и есть·
мой бот написан на bash-е, бот drBatty — на sed-е, бот Nazyvaemykh — на чём-то эукариотическом…
(улыбка)
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

t.t писал(а):
20.09.2011 11:51
А я так и не понял, зачем "без него", если "с ним" проще и короче.

"с ним" проще и короче если использовать сторонние утилиты, что противоречит условию.
t.t писал(а):
20.09.2011 11:51
Это был не "недостаток", а банальная техническая ошибка.

тут дело не в выходе из пайпа, а в группировке операций:
echo "x:y:z" | read a; echo ${a##*:}
вначале выполняется выделенная часть, а уж потом выполняется echo. При этом, a является локальной переменной.
нам это не нужно, потому и приходится использовать subshell
t.t писал(а):
20.09.2011 11:51

Код: Выделить всё

$ echo "x:y:z" | ( read a; echo ${a##*:} ) | cat
z

Вы пишете, что здесь выход из пайпа есть, хотя его по-прежнему нет.

почему "нет"? subshell в данном случае работает как фильтр, вроде sed/awk. Он получает данные из входного потока, обрабатывает их, и отдаёт в выходной. Как вы и заказывали:
1. внутри конвейера
2. на bash, без использования сторонних утилит.
Не понимаю, чем вас не устраивает этот вариант?
t.t писал(а):
20.09.2011 11:51
Параллельно sash-kan привёл и верное решение

я не нашёл решения от sash-kan в этой теме.
t.t писал(а):
20.09.2011 11:51
Думаю, явно не для того, чтобы этот дамп обрабатывать текстовыми утилитами. (;

а чем ещё дамп обрабатывать?

t.t писал(а):
20.09.2011 11:51
Я показал выше, что при почти четырёх тысячах символов в строке разница по времени пренебрежимо мала. А это явно избыточно: в моей задаче и пятисот символов быть не может.

t.t писал(а):
20.09.2011 11:51
У меня всё чаще возникает впечатление, что я с ботом разговариваю. В частности, очевидные вещи приходится по четыре раза проговаривать.

очевидно, что Ваши ограничения и условия надуманы, и я уже в какой раз возвращаюсь к своему первоначальному тезису - вы сами неоправданно сузили область решений - задача тривиально решается той-же sed (о чём вы писали ещё в первом посте), или без конвейера. Напоминает разложение в ряд функции y=1/x в начальной школе - дескать дети ещё не проходили деление, и разложение в бесконечный ряд с предельным переходом, или аппроксимация многочленом функции 1/x для них будет проще, ведь там нет деления - только сложение/вычитание/умножение...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение t.t »

sash-kan писал(а):
20.09.2011 13:12
мой бот написан на bash-е, бот drBatty — на sed-е
Да, именно так я и подозревал. (:

sash-kan писал(а):
20.09.2011 13:12
бот Nazyvaemykh — на чём-то эукариотическом…
А таких я и словей-то не знаю (ispell, кстати, тоже не знает).
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Получить часть строки до последнего : (или удалить последний символ в строке)

Сообщение drBatty »

sash-kan писал(а):
20.09.2011 13:12
так оно и есть·
мой бот написан на bash-е, бот drBatty — на sed-е, бот Nazyvaemykh — на чём-то эукариотическом…

ну вот... Нас раскрыли!
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: