URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 93519
[ Назад ]

Исходное сообщение
"Помогите с заменой слова в строке..."

Отправлено THEDECAL , 27-Июн-12 17:51 
Пишу скрипт и я не могу сообразить как поменять третье (150000) слово на "1" в строке:

#l# 1284725281 150000

учитывая, что третье слово может быть разной длиной, а второе всегда одинаковой, но с разными цифрами

Я примерно вот так начал писать, а дальше не соображу:

sed 's/^#l#\ [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\ /#l#\ "вот тут уже не соображу"' ahistory.dat


Содержание

Сообщения в этом обсуждении
"Помогите с заменой слова в строке..."
Отправлено stereoPANDA , 27-Июн-12 18:20 
echo "#l# 1284725281 150000" | awk '{print $1,$2,$3=1}'


> Пишу скрипт и я не могу сообразить как поменять третье (150000) слово
> на "1" в строке:
> #l# 1284725281 150000
> учитывая, что третье слово может быть разной длиной, а второе всегда одинаковой,
> но с разными цифрами
> Я примерно вот так начал писать, а дальше не соображу:
> sed 's/^#l#\ [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\ /#l#\ "вот тут уже
> не соображу"' ahistory.dat


"Помогите с заменой слова в строке..."
Отправлено Andrey Mitrofanov , 30-Июн-12 09:04 
>awk '{print $1,$2,$3=1}'

{$3=1;print}
{$NF=1;print}


"Помогите с заменой слова в строке..."
Отправлено Af. , 27-Июн-12 23:21 
Bash только:

shopt -s extglob
str="#l# 1284725281 150000"
echo "${str/% *([[:digit:]])/ 1}"
echo "или если слово с буквами и цифрами"
echo "${str/% *([[:alnum:]])/ 1}"

Sed:


str="#l# 1284725281 150000"
sed 's/ [0-9]*$/ 1/' <<< "${str}"

В обоих случаях использованы регулярные выражения, они ресурсоёмкие. А использование pipe "|" влечёт за собой +1 вызов экземпляра shell. На это, в свою очередь, тоже расходуются ресурсы-время. Какой из трёх вариантов (bash только, awk, sed) и в какой ситуации быстрее - не знаю.

Кстати, вопрос ко всем, что быстрее работает (или должно бы быть быстрее)?

P.S. Без регулярных выражений, Bash,
условившись о постоянной длине первых двух слов:


str="#l# 1284725281 150000"
str="${str:0:14} 1"
echo "${str}"
str="$(cut -c1-14 <<< "${str}") 1"
echo "${str}"


"Помогите с заменой слова в строке..."
Отправлено Af. , 27-Июн-12 23:25 
Забыл. :) Если без длины слов, но условие - меняем последнее в строке слово:

str="#l# 1284725281 150000"
str="${str% *} 1"
echo "${str}"


"Помогите с заменой слова в строке..."
Отправлено stereoPANDA , 27-Июн-12 23:54 
Af,
Что бы узнать, что быстрее работает - выполните time:
#time [command or script]
Насколько мне хватает компетенции, я могу сказать, что в "погоне за временем" стараются придерживаться нескольких правил:
1. Если все можно сделать на sed, то это будет быстрее чем sed + awk или + cut или + grep. Правило действует на все утилиты.
2. Меньше пайпов, это следует,в принципе, из правила 1.
3. sed работает быстрее всех. (это я где-то прочитал, проверял пару раз - поддтвердилось)

А что касается реализации решения задачи на bash, то прошу расписать как ваша конструкция работает, ибо я 1й раз такое вижу.

пс: а как вам  мое решение?

> Забыл. :) Если без длины слов, но условие - меняем последнее в
> строке слово:
>

 
> str="#l# 1284725281 150000"
> str="${str% *} 1"
> echo "${str}"
>

"Помогите с заменой слова в строке..."
Отправлено Af. , 28-Июн-12 19:46 
>> str="${str% *} 1"
>>
> как ваша конструкция работает, ибо я 1й раз такое вижу.
> пс: а как вам  мое решение?

Оно работает, что главное. С точки зрения простых манипуляций логами - не вижу принципиальных отличий между sed и awk. Склонен согласиться с http://stackoverflow.com/a/367014 Не могу оценивать с точки зрения сложных "рефаторингов" какого либо текста или кода. Но, не обладая доскональным пониманием синтаксисов как awk/sed, так и текста-цели, страшновато для сложных вещей "изобретать" собственные реализации инструментов на базе sed/awk и т.п. Неприятны вероятность ошибки и траты на исправления.

Конструкция ${parameter%pattern} описана в разделе Parameter Expansion из man bash. '%' - оператор отрезать суффикс от значения переменной. То что правее '%' - шаблон, что подходит под шаблон вырезается. Если % одиночный, цель наикратчайшее совпадение. Двойной - самое длинное. '% *' означает последний пробел и что правее него.


"Помогите с заменой слова в строке..."
Отправлено LSTemp , 30-Июн-12 00:03 
>>> str="${str% *} 1"
>>>
>> как ваша конструкция работает, ибо я 1й раз такое вижу.
>> пс: а как вам  мое решение?
> Оно работает, что главное. С точки зрения простых манипуляций логами - не
> вижу принципиальных отличий между sed и awk.

здесь Вы не правы:

основное преимущество sed, в том, что он ПОСТРОЧНО обрабатывает вход => минимальное потребление ресурсов ОС и независимость от размера входящего потока данных.

основное преимущество awk в том, что его гибкость (читай использование скриптов) позволяет выполнить практически любую операцию над входным потоком данных и включать его в КОНВЕЙЕР. Он в отличие от sed работает не построчно с входящими данными, а с их блоками, что позволяет организовать более тонкую обработку. Но ресурсов ОС жрет тоже не много

sed и awk - это классика.

>[оверквотинг удален]
> Не могу оценивать с точки зрения сложных "рефаторингов" какого либо текста
> или кода. Но, не обладая доскональным пониманием синтаксисов как awk/sed, так
> и текста-цели, страшновато для сложных вещей "изобретать" собственные реализации инструментов
> на базе sed/awk и т.п. Неприятны вероятность ошибки и траты на
> исправления.
> Конструкция ${parameter%pattern} описана в разделе Parameter Expansion из man bash. '%'
> - оператор отрезать суффикс от значения переменной. То что правее '%'
> - шаблон, что подходит под шаблон вырезается. Если % одиночный, цель
> наикратчайшее совпадение. Двойной - самое длинное. '% *' означает последний пробел
> и что правее него.

А тут я с Вами соглашусь. Поскольку задача явно скорее студенческого характера, то большие объемы данных обрабатывать вряд ли придется (sed/awk не нужен). Так что лучше пользоваться нативными средствами шела.