кримнаш в поштовій ізоляції

прочитав таке сьогодні у веселих свіжих новинах з кримнаша:
цитата | «Пошта США відмовилась доправляти посилки до окупованого Криму» (звідси).
вирішив перевірити. ситуація така…

королівська пошта (великобританія)

доставку до криму тимчасово призупинено з 18 березня 2014.
цитата | «Mail services to Crimea and Sevestapol are suspended until further notice» (сайт)

usps (національна пошта сша)

доставку до криму тимчасово призупинено з 17 червня 2014.
цитата | «In April, Ukrainian State Postal Enterprise (Ukrposhta) informed the Universal Postal Union that it had suspended delivery services for international mail addressed to Crimea (postal codes in the range 95000–99999)» (сайт)
щоправда, в повідомленні usps згадується, що обмеження не розповсюджується на fedex. йдемо до них…
колись у щоденнику:
цитата | «тим часом десь тут поруч тенетами гуляє росіянська страшилка про норвегію… оповідь якоїсь росіянки, що там пожила, повернулася і дає інтерв’ю про те, які там жахи творяться. погугліть, знайдеться швидко — це буде перший результат у видачі по коротесенькому запиту «норвегия интервью», що вже наводить на думки…» (їдьте і подивіться самі! 3 червня 2013)
зненацька історія отримала продовження: зустрів у стрічці google+ публікацію, котра добре ілюструє, звідки ноги ростуть!
цитата | «в последние пару лет в русскоязычном информационном пространстве о норвегии неожиданно стала появляться сенсационно шокирующая информация. репортаж за репортажем, статья за статьей, почти синхронно представляли норвегию как эпицентр зла и разврата таких масштабов, что содом и гоморра блекнут на её фоне. напомню основные утверждения, которые до сих пор активно циркулируют в интернете…» («как русские мамы извратили норвегию» 4 січня 2015)
залишилося тільки ці ноги відрізати. ну, бо перепоширення маячні психічно хворої людини буцім серйозними російськими медіа (втім, для нас це вже звучить смішно) — це вже має викликати занепокоєння в самих росіянців, ні?

підказка: скрипти bash без sed/cut/awk

в розділі tips, tricks and scripts англомовного форуму crunchbang знайшов цю підказку за авторством imbecil: як уникнути використання (чудових!) утиліт sed, cut і awk для нескладної обробки текстових рядків у bash-скриптах. стаття досить детально викладена, з прикладами — тож вирішив перекласти повністю і зберегти тут собі на згадку.

може ще комусь стане в пригоді? тоді не полінуйтеся, будь ласка, зареєструватися на форумі й подякувати авторові =)

1. вступ
2. приклади
  2.1. спосіб «sed+cut»
  2.2. спосіб «лише bash»
3. швидкодія
  3.1. тестовий скрипт
  3.2. результати тестування швидкодії
4. заключне слово

1. вступ

що?

чимало скриптів bash часто потребують інформації з текстових змінних (або з виводу команд), приміром:

variable="   якийсь текст XXXX-YYYY-ZZ 0xab2345 траляля"
#         ^^^ зауважте пробіли на початку текстового рядка


потребуючи й сам такого і шукаючи рецептів у тенетах, я помітив, що більшість пропонованих рішень використовують утиліти sed, cut та/або awk в різних комбінаціях. найчастіше текстовий рядок спрощують за допомогою sed, і згодом «вирізають» потрібну частину рядка за допомогою cut чи awk.

чому?

будучи впертим (уникаю використання python/ruby/perl) пуристом (навіщо викликати сторонні утиліти на кшалт sed у випадках, коли bash і сам достатньо потужний), я натрапив на згадку про «дивовижну кількість команд для операцій з текстовими рядками» та «масиви», інтегровані у bash, і відкрив для себе, що чимало операцій можна запрограмувати за допомогою цих команд замість вдаватися до запуску sed, cut і awk. а оскільки більшість пошукових запитів у google приводять саме на рецепти з sed/cut/awk, мені видалося непоганою ідеєю порекламувати інтегровані команди bash за допомогою кількох прикладів.

як?

робиться це навдивовижу просто, і, на мою гадку, семантично елегантніше в порівнянні до рецептів з sed, cut і awk. є певні недоліки, зокрема деякі однорядні команди (one-liners) неможливо зконструювати в силу особливостей роботи команд bash. для обробки тексту і масивів, проте загальне враження таке, що використання інтегрованих команд bash робить скрипти більш зрозумілими для читання.

далі йтимуть декілька прикладів…

2. приклади

гаразд, ось дуже простий приклад. я хочу витягти кожне чотирицифрове число в окрему змінну рядка на кшалт такого:

1680x1050+2880+23


звісно, неважко впізнати звичний рядок з «геометрією» дисплея, такі видає команда xrandr.

2.1 спосіб «sed+cut»

ось простий скрипт, щоби зробити це за допомогою sed:

# приклад SED
# задаймо текстовий рядок
xrandroutput="1680x1050+2880+23"

# визначмо символ табуляції TAB ('\t')
# знадобиться для sed та cut
TAB=$(echo -e "\t")

# замінімо «x» на тауляцію '\t'
array=`echo "$xrandroutput" | sed "s/x/$TAB/"`

# замінімо «+» на табуляцію '\t'
array=`echo -e "$array" | sed "s/+/$TAB/g"`

# збережімо потрібні значення
H=`echo -e "$array" | cut -f 1`
W=`echo -e "$array" | cut -f 2`
X=`echo -e "$array" | cut -f 3`
Y=`echo -e "$array" | cut -f 4`


гакери скрикнуть: «навіщо sed двічі?!» — і матимуть рацію, скрипт можна трошки скоротити:


# приклад SED
# задаймо текстовий рядок
xrandroutput="1680x1050+2880+23"

# визначмо символ табуляції TAB ('\t')
# знадобиться для sed та cut
TAB=$(echo -e "\t")

# замінімо «x» і «+» на тауляцію '\t'
array=`echo "$xrandroutput" | sed "s/[x+]/$TAB/g"`

# збережімо потрібні значення
H=`echo -e "$array" | cut -f 1`
W=`echo -e "$array" | cut -f 2`
X=`echo -e "$array" | cut -f 3`
Y=`echo -e "$array" | cut -f 4`


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

2.2 спосіб «лише bash»

а тепер обіцяний приклад використання лише інтегрованих команд bash:

# приклад ARRAY
# задаймо текстовий рядок
xrandroutput="1680x1050+2880+23"

# замінімо всі «x» на пробіли « », скориставшись
# потужною інтегрованою в bash командою заміни
# тексту за шаблоном:
# ${string//substring/replacement},
# і збережімо результат до змінної «array»
# (поки що це не масив)
array=${xrandroutput//x/" "} # результат: "1680 1050+2880+23"

# замінімо всі «+» на пробіли « » і збережімо
# результат тепер як масив у змінній «array»,
# використавши дужки «(» і «)»
# заувага: дужки приймають пробіл як роздільник
# і таким чином створюють масив значень
array=( ${array//+/" "} ) # результат: ( "1680" "1050" "2880" "23" )

# надрукуймо результат
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
echo "array[2] = ${array[2]}"
echo "array[3] = ${array[3]}"


звісно ж дві команди заміни можна об’єднати в одну:

# приклад ARRAY-SINGLE
...
# замінімо всі «x> і «+» на пробіли « »
# і збережімо результат в масив з назвою «array»
array=( ${xrandroutput//[x+]/" "} )
...


ну хіба ж не простіше і зрозуміліше? вже мовчу про те, що на виході всі дані маємо в одному масиві, а це досить зручно і не захаращує код назвами змінних.

аж зголоднів, поки писав це. мушу щось з’їсти і хильнути пива, перш ніж перейти до тестування швидкодії.

3. швидкодія

3.1 тестовий скрипт

чи справді варто використовувати інтегровані команди bash для обробки рядків і масивів, — а чи може це лише альтернативний спосіб і не більше? можна прогнати кілька тестів і подивитися, скільки за часом виконується кожен варіант. спершу я поясню, як саме я тестував. далі подаю чернетку тестового скрипта. ідея проста: запустити декілька (багато) подібних прикладів і заміряти час виконання.

#!/bin/bash
# використання: test [кількість_ітерацій]

iter=10000
# перевірмо, чи задано кількість ітерацій в командному рядку
if [ -n "$1" ]
then
iter="$1"
fi

TAB=$(echo -e "\t")

# проженімо ітерації
for i in `seq $iter`
do
#
# робочий код для тестування
#
done


цей тестовий скрипт запускається таким чином:

$ /usr/bin/time -f "\nReal: %E\nUser: %U\nSys: %S" ./test 100000


всередині циклу «do … done» вміщуємо тестовий код (я прибрав коментарі задля компактності):

# приклад SED
xrandroutput="1680x1050+2880+23"
array=`echo "$xrandroutput" | sed "s/x/$TAB/"`
array=`echo -e "$array" | sed "s/+/$TAB/g"`
H=`echo -e "$array" | cut -f 1`


а потім другий варіант:

# приклад ARRAY
xrandroutput="1680x1050+2880+23"
array=${xrandroutput//x/" "} # "1680 1050+2880+23"
array=( ${array//+/" "} ) # ( "1680" "1050" "2880" "23" )


зауважте, що у варіанті «приклад SED» ми змушені зберігати результат до змінної «H», тоді як у варіанті «приклад ARRAY» всі чотири значення зберігаються в одному масиві з доступом через «array[i]».

3.2 результати тестування швидкодії

щоби отримати надійний результат, я прогнав кожен тест кілька разів (міг би зробити це більш системно, підбивши якусь статистику, проте різниця настільки разюча, що в цім не було необхідности). далі я спробвав підібрати кількість ітерацій так, щоби скрипт виконувався приблизно 10 секунд, і таким чином нормалізувати результати.

а результати такі:

приклад SED: 1000 ітерацій = 2,17 секунд
приклад ARRAY: 1000 ітерацій = 0,011 секунд


так, різниця 200-кратна на користь варіанту «приклад ARRAY». отже, інтегровані команди bash працюють значно швидше, ніж виклик sed.

дивно? ну, я очікував дещо вищої продуктивності, але ж не 200-кратно… насправді, тут я запрошую знавців написати оптимальніший код з використанням sed. можливо, це можна зробити краще, ніж вийшло у мене.

4. заключне слово

отже, чи варто користуватися інтегрованими командами bash? спробую підсумувати:

переваги (аргументи на користь внутрішніх команд bash:
+ це значно швидше;
+ код зрозуміліший (на мою думку), з меншою кількістю змінних;
+ мені здається, що це простіше програмувати.

недоліки (проти):
– значна залежність від bash;
– хоча масиви і команди обробки рядків мають бути доступні в сучасних версіях bash (вище третьої), все-таки можуть виникати проблеми сумісності в старших версіях;
– неможливо реалізувати деякі однорядкові команди (one-liners), які досить просто отримати перенаправленням виводу.

наостанок кілька слів:

а) сподіваюся, комусь це стане в нагоді. розумію, що хтось скаже: «о, я це й так знав», інші запитають «про що це він взагалі говорить?», проте я таки сподіваюся, що хтось навчиться чогось нового;
б) перепрошую, що не спромігся пояснити коротше; також перепрошую за кострубату англійську;
в) не соромтеся збиткуватися з мене, якщо я десь тут припустився помилки.

кінець.

enjoy «руськє мір», пля!

в мене складається враження: що б не казав москаль, як би жалісливо не співав — на споді там завжди імперське гниле болото міфів і, в загальному, місце україни та українця в тих міфах чітко визначене =(

почитайте, приміром, ось це інтерв’ю прогресивної російської журналістки-фотографа вікторії івлєвої:

http://gordonua.com/publications/58642.html

на перший погляд — мед і патока, ну чисто тобі бандерівка і затятий український патріот. читаємо:
Г: Мне показалось, вы знаете о людях Донбасса больше, чем украинские политики…
В.І.:Они тоже все знают. Но мыслят какими-то миллиардами, неизвестно зачем посылают своих жен с гуманитарным конвоем, как будто это рекламная увеселительная прогулка.
ну звісно. будь ти хоч тричі про-український росіянин, в тебе язик не повернеться нічого сказати про українську владу, якщо це лише не критика. це, мабуть, на підкірці, глибше за підсвідомість. втім, ми й самі владу любимо покритикувати. читаймо далі.

переворот у воді…

я мушу, врешті-решт, цього навчитися! тим більше, що виглядає ж нескладно…

все по сто!

найцікавіше вдома відбувається, поки чоловік на роботі. ні, не те, що ви могли подумати =)

мала доця (п’ять з половиною років) випрошує солодощі, погоджується на плитку молочного шоколаду. миленька, змучившись відмовляти, дає донечці 20 грн і відправляє до крамниці — мовляв, придбай, що забажаєш. мала йде…

…і повертається з пустими руками. на питання «чому?» відказує:

— в мене лише двадцять гривень, а там все по сто!

виявилося, що вона, в міру своїх знань, чемно читала кожну упаковку з шоколадками, і всюди знаходила «100 гр» =)