якое павялічваецца колькасць ва ўдары з вядучымі 0

Я вельмі пачатковец у Баш сцэнарыяў, і я спрабую напісаць код для разбору і маніпуляваць файл, які я працую на.

Мне трэба павялічваць або памяншаць у хвіліну часу, за кучу розных часоў у файле. Мая праблема ўзнікае, калі час, напрыклад, 02:04 ці 14:00.

Прыклад файла:

2:43
2:05
15:00

Мой бягучы урывак з маёй Баш скрыпт, як гэта

for x in `cat $1`;
  do minute_var=$(echo $x | cut -d: -f2);
  incr_min=$(($minute_var + 1 | bc));
  echo $incr_min;
done

Бягучы вынік:

44
6
1

Патрабаваны вынік:

44
06
01

любыя прапановы

0
Няма неабходнасці ў дарагіх труб AN відэльцаў: minute_var = $ {х # *:} выдаляе ўсе Шыфраванне да і уключаючы першы : .
дададзена аўтар Jens, крыніца
Проста з цікаўнасці, гэта добра для 59, каб павялічыць да 60, ці ён павінен загарнуць да 00?
дададзена аўтар tripleee, крыніца
Нават у Баш, добрая практыка, каб аддзяліць выгляд і мадэль. Спосаб адлюстравання нумары не павінны перашкаджаць тым, як яны павялічваюцца.
дададзена аўтар mouviciel, крыніца
@Jens: Нават $ {х # *:} можа быць прапушчаны, выкарыстоўваючы у той час як МФС =: чытання ч мін; рабіць . Пратакол будзе чытаць мін непасрэдна. І ніякая знешняя ўтыліта не патрабуе, каб выкарыстоўваць (не кошка , выразаць або Ьс ).
дададзена аўтар TrueY, крыніца

8 адказы

Выкарыстоўвайце Printf :

incr_min=$(printf %02d $(($minute_var + 1 )) )

Няма, што Ьс не патрэбны, калі толькі цэлыя лікі ўдзельнічаюць.

3
дададзена
@TrueY, Printf гэта Баш убудаваныя - гл увядзіце -a Printf
дададзена аўтар glenn jackman, крыніца
Вы ўдар пытанні васьмярковых - тэст з часам «08:08». Вам трэба $ ((10 # $ minute_var + 1))
дададзена аўтар glenn jackman, крыніца
@glennjackman: Я тэставаў трассированием. У выпадку $ (Printf ...) а клон закліканы стварыць даччыны працэс кожны раз. Калі Printf -v ... выкарыстоўваецца, то ні адзін дзіця не будзе створаны. Такім чынам, пазней выкарыстоўвае менш рэсурсаў.
дададзена аўтар TrueY, крыніца
На самай справе Printf таксама знешні ўтыліта. Таксама не патрабуецца ў дадзеным выпадку.
дададзена аўтар TrueY, крыніца
@glennjackman: Yepp! Вы маеце рацыю! Дзякуй за інфармацыю! Можа быць, замест таго, каб incr_min = $ (Printf ...) клавішы Printf -v incr_min ... можа быць выкарыстаны.
дададзена аўтар TrueY, крыніца
while IFS=: read hour min; do 
    printf "%02d\n" $((10#$min + 1))
done <
44
06
01
09
60

За хвіліну абгорткі да наступнага гадзіны, выкарыстоўваць мову з функцыямі часу, як прасцяк

awk -F: '{
    time = mktime("1970 01 01 " $1 " " $2 " 00")
    time += 60
    print strftime("%M", time)
}' 
perl -MTime::Piece -MTime::Seconds -nle '
    $t = Time::Piece->strptime($_, "%H:%M");
    print +($t + ONE_MINUTE)->strftime("%M");
'
1
дададзена
Добрае пытанне. Вы <�я> магу </я> рэалізаваць абгортачную логіку самастойна ў Баше, але прапусцілі б выпадкі кутніх.
дададзена аўтар Charles Duffy, крыніца

гэта нармальна для вашага патрабаванні?

kent$  echo "2:43
2:05
15:00"|awk -F: '{$2++;printf "%02d\n", $2}'
44
06
01
1
дададзена

<�Моцны> АБНОЎЛЕНА # 2

There are some problems with your script. At first instead of `cat file` you should use ` or rather $(. One fork and exec call is spared as bash simply opens the file. On the other hand calling cut and bc (and printf) also not needed as bash has internally the proper features. So you can spare some forks and execs again.

Калі ўваходных файл з'яўляецца вялікім (больш чым прыблізна 32 KiB), то для -loop лінія можа быць занадта вялікі, каб быць апрацаваны Баш таму я прапаную выкарыстоўваць у той час як -loop замест і прачытаць файл радок за радком.

Я мог бы прапанаваць нешта падобнае ў чыстым баш (прымяняецца рашэнне SubStr ATLE в):

while IFS=: read hr min; do
  incr_min=$((1$min+1)); #Octal problem solved
  echo ${incr_min: -2}; #Mind the space before -2!
  #or with glennjackman's suggestion to use decimal base
  #incr_min=0$((10#$min+1))
  #echo ${incr_min: -2};
  #or choroba's solution improved to set variable directly
  #printf -v incr_min %02d $((10#$min+1))
  #echo $incr_min
done 

ўваходных файл

$ cat file
2:43
2:05
15:00
12:07
12:08
12:09

выхад:

44
06
01
08
09
10

Можа быць, Printf -v з'яўляецца найбольш простым, як ён змяшчае вынік у зменную ў адным кроку.

Добры пытанне ад tripleee , што павінна адбыцца, калі вынік роўны 60.

1
дададзена
Вы ўдар пытанні васьмярковых - тэст з часам «08:08». Вам трэба $ ((10 # $ {х # *:} + 1))
дададзена аўтар glenn jackman, крыніца
@glennjackman: Вы абсалютна маеце рацыю! Дзякуй за гэта! Адказ выпраўлены.
дададзена аўтар TrueY, крыніца

Padding з 0, і атрыманне двух апошніх знакаў:

for x in `cat $1`;
  do minute_var=$(echo $x | cut -d: -f2);
  incr_min=0$(($minute_var + 1 | bc));
  echo ${incr_min: -2:2};
done
1
дададзена
(Каб было ясна, чаму вынікаючы гэтым узоры можа прывесці да няправільным выніках ў іншых выпадках выкарыстання - думаю, ўсячэнне).
дададзена аўтар Charles Duffy, крыніца
Хм. На самай справе - за хвіліну значэнне ў той час, гэта па меншай меры будзе даваць правільныя вынікі. Для чагосьці, дзе дапушчальнае значэнне можа выкарыстоўваць больш за два лічбаў, вы хочаце выкарыстоўваць Printf -v padded_value% 02d «$ value_to_pad» замест гэтага. Тым не менш, я абсалютна не прымаю перадумову, што дае правільныя вынікі гэта адзінае, што трэба, каб быць прымальным адказам; Ніжэй лепшыя пытанні практыкі.
дададзена аўтар Charles Duffy, крыніца
@Atle Не толькі мой мазоль. Вазьміце гэты код на #bash FreeNode і паглядзець, што людзі думаюць.
дададзена аўтар Charles Duffy, крыніца
@Atle Piping да Ьс выкарыстоўвае знешні інструмент для таго, што было зроблена раней для ўнутранага Баш. Таму што ў субоболочке, патрабуецца відэлец() выклік, элемент EXEC() , а чытаць() і г.д., і у адваротным выпадку значна неэфектыўны. Шлях UNIX мяркуе выкарыстанне многіх інструментаў, якія працуюць на адным інтэрфейсе (струмень), - так, але гэта не падстава для неэфектыўнасці.
дададзена аўтар Charles Duffy, крыніца
Ня цытую, калі гэта неабходна, ёсць шмат непатрэбных трубаправоды, ігнаруе убудаваныя функцыі абалонкі, якая робіць працу лепш.
дададзена аўтар Charles Duffy, крыніца
Падзяку за $ {::} ідэі. Але не трэба выклікаць якія-небудзь знешнія утыліты, такія як кошка , Выразаць і Ьс .
дададзена аўтар TrueY, крыніца
@CharlesDuffy Ідэя паліцэйскіх рашэнняў на аснове вашых асабістых (ці некаторых форумах) крытэрыі проста нявыхаванасць. Замест гэтага вы павінны паказаць на фактычныя памылкі, даваць тлумачэньні, дэманстрацыі паляпшэнняў і іншыя варыянты; як правіла, вучыць іншых, як зрабіць што-то разумнейшы.
дададзена аўтар Atle, крыніца
@CharlesDuffy Маючы код ацэненую па зусім розных крытэрах, чым у арыгінальных плакатаў абсалютна ніякага значэння тут. І зноў: Рашэнне, якое я пры ўмове не роўна поўным код. Я паказаў, як падушачка і экстракт. Гэта рашэнне не дрэнна толькі таму, што я выкарыстаў яго ў кантэксце ўжо дадзена.
дададзена аўтар Atle, крыніца
@CharlesDuffy Таксама «эфектыўнасць» ваша мазоль, не з'яўляецца абавязковым патрабаванне ў гэтым пытанні. Ніхто не мае патрэбы ў excusion ня быць аптымальна эфектыўным, калі эфектыўнасць не з'яўляецца абавязковым патрабаваннем. Большасць * NIX сістэм ручкі марнаваць некалькі цыклаў стварэння і знішчэння працэсаў вельмі добра.
дададзена аўтар Atle, крыніца
@CharlesDuffy Маё рашэнне не выкарыстоўвае трубаправоды ў БЛ. Маё рашэнне складаецца ў калодкі пачатак радка з 0, а затым выкарыстоўваць {: -2: 2}, каб атрымаць апошнюю частку зменнай. Што вы каментуючы тут зыходны код.
дададзена аўтар Atle, крыніца
@CharlesDuffy, што я зрабіў змены кода ў зыходны пытанне, каб паказаць шлях вырашэння гэтай праблемы. Мае мадыфікацыі з дапамогай убудаваных у функцыянальнасці абалонкі, а не выкарыстоўваць трубы. І нават калі б яны зрабілі, няма нічога дрэннага наогул з выкарыстаннем розных інструментаў разам, каб вырашыць праблемы. На самай справе, гэта значыць * Нікс шлях.
дададзена аўтар Atle, крыніца

Вось рашэнне, якое

    <�Літый> абгортваюць секунд ад 59 да 0
  • не з'яўляецца цалкам POSIX сумяшчальны - няма bashisms
  • не патрэбны ні адной відэльцам, такім чынам, вельмі хутка
$ cat x
2:43
2:05
2:08
2:09
15:00
15:59
$ while IFS=: read hr min; do
   printf '%02d\n' $(((${min#0}+1)%60))
done < x
44
06
09
10
01
00
0
дададзена
@glennjackman Дзякуй; ён працаваў у Zsh; фіксаванай працаваць у любой абалонцы Борна як Баш, які будзе паскардзіцца 08: значэнне занадта вялікі для базы (маркер памылкі «08») .
дададзена аўтар Jens, крыніца
не працуе з раз заканчваецца ў 08 або 09
дададзена аўтар glenn jackman, крыніца

Выкарыстоўвайце PRINTF перафарматаваць выхад быць нулямі, 2-шырокая:

incr_min=$(printf %02d $incr_min)
0
дададзена

Паспрабуйце гэта:

for x in $(<$1); do
    printf "%02d\n" $(((${x#*:}+1)%60));
done
0
дададзена