LINUX.ORG.RU
решено ФорумAdmin

Изменить дату внутри строки стандартными средствамм

 , , ,


0

1

Дано - файл с содержимым в виде строк AAAAAA 2018-01-26 BBBBBB.надо дату сделать формата 26-01-18.
Как можно это стандартными методами типа grep sed awk?

На руби это делается с полтычка, но хочется сделать это через grep sed awk

★★★★

Последнее исправление: yu-boot (всего исправлений: 5)

<...> с полтычка <...>

$ echo AAAAAA 2018-01-26 BBBBBB | sed -r 's/(.*) ..(.*)-(.*)-(.*) (.*)/\1 \4-\3-\2 \5/'
AAAAAA 26-01-18 BBBBBB
Deleted
()
Ответ на: комментарий от Deleted

я бы не (.*) использовал (что значит «любой символ 0 или несколько раз), а точное совпадение с цифрами формата YYYY-MM-DD

# echo AAAAAA 2018-01-26 BBBBBB | sed -r 's/(.*) ..([0-9]{2})-([0-9]{2})-([0-9]{2}) (.*)/\1 \4-\3-\2 \5/'
AAAAAA 26-01-18 BBBBBB
bvn13 ★★★★★
()
Последнее исправление: bvn13 (всего исправлений: 1)
echo 'AAAAAA 2018-01-26 BBBBBB' | gawk '{
 split($2,a,"-");
 a[1]=substr(a[1],3); 
 $2=a[3]"-"a[2]"-"a[1]; 
 print}'
futurama ★★★★★
()

с полтычка

futurama, на awk даже специальная функция есть для subj

echo 'AAAAAA 2018-01-26 BBBBBB' | awk '/^AAAAAA [0-9]{4}-[0-9]{2}-[0-9]{2} BBBBBB/ { print gensub(/..(..)-(..)-(..)/, "\\3-\\2-\\1", 1)}'

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от futurama

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

vodz ★★★★★
()

sed is a Stream EDitor; use ex

$ ex -sc '%s/ \(\d\{4\}\)-\(\d\d\)-\(\d\d\) / \3-\2-\1 /g|x' file


Кошэрно, портабельно, POSIX-совместимо.

mos ★★☆☆☆
()

(всего исправлений: 5)

вэп программисты они особенные...

mos ★★☆☆☆
()

Если регулярка будет составлена верно и формат даты меняться не будет, то

sed -ir file.txt

будет достаточно.

Deleted
()
Ответ на: комментарий от vodz

Ой, не факт.

regexp медленнее, это плата за гибкость

$ cat benchawk.sh 
#!/bin/bash

gen_file() {
test -e $1 || for ((i=0; i<1000000; i++))
do
        echo AAAAAA 2018-01-26 BBBBBB
done > $1
}

bench_awk_re() {
  cat $1 | awk '/^.* [0-9]{4}-[0-9]{2}-[0-9]{2} .*/ { print gensub(/..(..)-(..)-(..)/, "\\3-\\2-\\1", 1)}'
}

bench_awk_subst() {
 cat $1 | gawk '{
 split($2,a,"-");
 a[1]=substr(a[1],3); 
 $2=a[3]"-"a[2]"-"a[1]; 
 print}'
}

F=/tmp/bench_awk.txt
gen_file $F

echo regexp
time bench_awk_re $F >/dev/null
echo -------
echo subst
time bench_awk_subst $F >/dev/null
$ ./benchawk.sh 
regexp

real    0m2,449s
user    0m2,617s
sys     0m0,004s
-------
subst

real    0m1,046s
user    0m1,042s
sys     0m0,045s

Deleted
()
Ответ на: комментарий от Deleted

sed is a Stream EDitor, not a file editor.

Nevertheless, people everywhere tend to abuse it for trying to edit files. It doesn't edit files.
GNU sed (and some BSD seds) have a -i option that makes a copy and replaces the original file with the copy.
An expensive operation, but if you enjoy unportable code, I/O overhead and bad side effects (such as destroying symlinks), this would be an option

mos ★★☆☆☆
()
Ответ на: комментарий от Deleted

по крайней мере, ни название sed, ни то что люди его используют не по назначению заложенному в названии, ни нестандартность ключа -i точно не устарели. как наверное и то что линки убьются при таком использовании.
а вот на сравнение производительности sed -i и ex/ed я бы тоже глянул.

mos ★★☆☆☆
()
Ответ на: комментарий от Deleted

А это ничего, что у меня там два regex, а сравниваете вы с вариантом, где вообще входная строка не проверяется?

vodz ★★★★★
()
Ответ на: комментарий от vodz

О том и речь. Если регулярку предельно упростить и применять один раз, то скорость вырастет в разы.

$ bench_fast() { cat $1 | awk '{ print gensub(/ ..(..)(-..-)(..) /, " \\3\\2\\1 ", 1)}'; }
$ time bench_fast /tmp/bench_awk.txt >/dev/null

real    0m0,958s
user    0m0,946s
sys     0m0,069s
Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

О том и речь.

Нет. Прежде чем вклиниваться в диспут стоило бы разобраться о чём речь.

Речь была о gensub() vs split()+substr()+другие строчные выражения.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

Прежде чем вклиниваться в диспут стоило бы разобраться о чём речь.

Мне казалось это очевидным. Хорошо, тогда напишу свою мысль подробно.

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

При использовании regexp'ов скорость напрямую зависит от того, насколько он сложен.

Deleted
()
Ответ на: комментарий от Deleted

Мне казалось это очевидным.

Что это? Вы ведь так и не прочитали исходное возражение и не вникли...

другое несколько операций на интерпретаторе

Прочитайте внимательнее! Речь была о том, что когда у нас gensub() vs split() то то что regex-ы тормознее ясен пень никто не спорил. Но вот когда к split() добавляется несколько ЕЩЁ операторов, и они не компилируются, а интерпретируются, то в СУММЕ не факт, что один regex будет их тормозней. Но сравнивать надо сравнимое, то есть до split надо либо добавить regex по поиску правильной исходной строки либо убрать первый regex у моего примера.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Что это? Вы ведь так и не прочитали исходное возражение и не вникли...

Читаем вместе:

Ответ на: с полтычка от vodz 23.11.2018 10:19:49
Re: с полтычка

Я не хочу regexp, split дешевле
futurama ★★ (23.11.2018 10:22:09)
Ответ на: Re: с полтычка от futurama 23.11.2018 10:22:09

Ой, не факт. Одно дело был бы компилируемый язык, другое несколько операций на интерпретаторе, что ниверирует более быстрые функции.
vodz ★★★ (23.11.2018 10:24:50)

split дешевле

Но сравнивать надо сравнимое, то есть до split надо либо добавить regex по поиску правильной исходной строки либо убрать первый regex у моего примера.

Надо, так надо. Давайте сравним на большом файле со случайными данными оба варианта.

$ cat b_comparable.sh 
#!/bin/bash

gen_file() { test -e $1 || cat /dev/urandom | base64 | head -n 5000000 | awk '{ print $0" "strftime("%Y-%m-%d %H:%M:%S",NR) }' > $1; } 
b_re_split() { cat $1 | awk '/^.* [0-9]{4}-[0-9]{2}-[0-9]{2} .*/ { split($2,a,"-"); print $1" "a[3]"-"a[2]"-"substr(a[1],3)" "$3 }';  }
b_re_gensub() { cat $1 | awk '/^.* [0-9]{4}-[0-9]{2}-[0-9]{2} .*/ { print gensub(/..(..)-(..)-(..)/, "\\3-\\2-\\1", 1) }'; }
b_all_split() { cat $1 | awk '{ split($2,a,"-"); print $1" "a[3]"-"a[2]"-"substr(a[1],3)" "$3}'; }
b_all_gensub() { cat $1 | awk '{ print gensub(/..(..)-(..)-(..)/, "\\3-\\2-\\1", 1) }'; }

F=/tmp/b_comparable.txt
gen_file $F
for P in b_re_split b_re_gensub b_all_split b_all_gensub; do echo $P; time $P $F > /dev/null; echo;  done
$ ./b_comparable.sh 
b_re_split

real    0m23,715s
user    0m23,574s
sys     0m1,155s

b_re_gensub

real    0m48,202s
user    0m48,113s
sys     0m3,410s

b_all_split

real    0m5,463s
user    0m5,310s
sys     0m0,424s

b_all_gensub

real    0m30,267s
user    0m30,118s
sys     0m3,375s
split дешевле

Deleted
()
Ответ на: комментарий от Deleted

split дешевле

Вы русский разумеете? Выражение «не факт» не означает, что 100% не факт, а означает, что говорящий не знает факт и стоит возможные предположения. Есть ли в этом полезное? Безусловно. 23 секунды могут легко вырасти и в 48+ если задачу чуть усложнить, скажем, то что можно было б извлечь более сложным одним regex, пришлось бы еще наворотить еще груду split+substr. И именно об этом и стояла простейшая мысль, которую вы уже 5-й раз не можете распарсить.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Вы русский разумеете?

Сохраняем нейтрально-уважительный стиль общения.

23 секунды могут легко вырасти и в 48+ если задачу чуть усложнить, скажем, то что можно было б извлечь более сложным одним regex, пришлось бы еще наворотить еще груду split+substr. И именно об этом и стояла простейшая мысль, которую вы уже 5-й раз не можете распарсить.

...И это будет другой задачей, и она будет решаться иначе и, возможно, при её решении манипулирование подстроками не будет таким эффективным вариантом обработки файла. При использовании regexp'ов скорость напрямую зависит от того, насколько он сложен.

Для данной конкретной задачи, решение со split и substr показывает лучшую производительность, чем предложенный вами вариант с gensub и regexp.

Это экспериментально проверенный факт. Это было очевидно и без проведения тестов, потому, что split дешевле, чем regexp.

Deleted
()
Ответ на: комментарий от Deleted

И это будет другой задачей,

Не обязательно. Под AAAA и BBBB может быть что угодно, и это сразу в вашей терминологии получит требование all -> re. А там уже и разница не столь внушительна.

Это экспериментально проверенный факт. Это было очевидно и без проведения тестов, потому, что split дешевле, чем regexp.

О, Боже... Как де вы достали тупить. Последний раз и похоже вас уже пора в игнор. Если задача приводит к нескольким операциям, то при опередленных условиях может оказаться, что один regex быстрее чем совокупность нескольких последовательных более простых операция над строками.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Не обязательно. Под AAAA и BBBB может быть что угодно, и это сразу в вашей терминологии получит требование all -> re. А там уже и разница не столь внушительна.

Да, не обязательно. Предложите свой testcase, и тогда будет о чём говорить.

О, Боже... Как де вы достали тупить. Последний раз и похоже вас уже пора в игнор.

Вы несдержанны в словах, это печально.

Если задача приводит к нескольким операциям, то при опередленных условиях может оказаться, что один regex быстрее чем совокупность нескольких последовательных более простых операция над строками.

Где и когда я это отрицал?

Deleted
()
Ответ на: комментарий от Deleted

Где и когда я это отрицал?

Откуда я знаю, зачем вы развели эту бодягу? Ибо это одна и та же мысль, сказанная и так и этак раз 5 и как и всякая обтекаемая совершенно не требующая никаких жарких споров, но вы же с завидной энергией под до что-нибудь бы более полезное, ринулись в бой.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от bvn13

В итоге взял этот вариант. Только прошлось посношаться с ; И как разделителем команд sed, И как с элементом регекспа


find /home/yu/smg-cdr -name "*.cdr" -exec sed -r 's/\;/ /g; s/(.*) ..([0-9]{2})-([0-9]{2})-([0-9]{2}) (.*)/\1 \4-\3-\2 \5/'  {} >> /home/yu/cdr.txt \; -exec rm -f {} \;
yu-boot ★★★★
() автор топика
20 апреля 2019 г.
Ответ на: комментарий от yu-boot

Комрады не стал тему создавать, помогите применить команду на последний столбец $NF

awk 'BEGIN {OFS="/"}{print substr($1,5,2), substr($1,7,2), substr($1,1,4)}'

Было

19790513
19790513
20000901
Стало
05/13/1979
05/13/1979
09/01/2000

Заранее спасибо.

rusic
()
Ответ на: комментарий от rusic

Комрады, кто поможет за чашку кофе скрипт awk подшаманить? P.S. В моем верхнем посте не тот скрипт.

rusic
()
Ответ на: комментарий от rusic

помогите применить команду на последний столбец

Чего надо то? Это, что ле?:

$ awk 'BEGIN {OFS="/"}{print substr($1,7,2), substr($1,5,2), substr($1,3,2)}'
Deleted
()
Ответ на: комментарий от Deleted
dfdfdfdfd 71901520080000234 ИВАНОВА СВЕТЛАНА ПАВЛОВНА 21/10/1972 15/04/2018 00/00/0000
dfdfdfdfd 51901520083000165 БЕЛОВ ДМИТРИЙ ВАЛЕРЬЕВИЧ 21/03/1944 11/03/2019 00/00/0000 
fhghgfhgf 61901520080000197 ГУЩИН ПАВЕЛ 01/07/1936 24/03/2017 00/00/0000 

Нужна замена через awk последних трех столбцов на формат yyyymmdd

rusic
()
Ответ на: комментарий от rusic

последних трех столбцов на формат yyyymmdd

Не стал заморачиваться, сделал «по-тупому»:

$ rev test.txt | awk '{ print $1 " " $2 " " $3 }' | rev | awk '{ print substr($1,7,4) substr($1,4,2) substr($1,1,2), substr($2,7,4) substr($2,4,2) substr($2,1,2), substr($3,7,4) substr($3,4,2) substr($3,1,2) }'
Deleted
()
Ответ на: комментарий от rusic

скажите какие нужны?
sed есть

Забей:

$ awk '{ i = (NF - 2); j = (NF -1); k = NF; print substr($i,7,4) substr($i,4,2) substr($i,1,2), substr($j,7,4) substr($j,4,2) substr($j,1,2), substr($k,7,4) substr($k,4,2) substr($k,1,2) }' test.txt
Deleted
()
Ответ на: комментарий от Deleted

3 последних столбца меняются, но в итоге они только и остаются

rusic
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.