What does git log --since/--until do when there is no HH:MM:SS supplied in the value? - git-log

Reference the answer at https://stackoverflow.com/a/19987337/257924 to the question of How do I view all commits for a specific day?
What is the value of HH:MM:SS referenced below that would make the output of the following command be true across all git repositories regardless of history and content:
git log --since='2019-12-25' --until='2019-12-26 00:00:00'
git log --since='2019-12-25 HH:MM:SS' --until='2019-12-26 00:00:00'
I ask because the man-page for git-log does not provide that detail (or I missed it).
TL;DR Experiment
Try this on your own git repos, and be as baffled by the output as I am by the fact that all of the one after the first combination yield differences in git log output:
$ for x in "" "00:00:00" "23:59:59"
do
for y in "" "00:00:00" "23:59:59"
do
printf "x %-10s y %-10s --> " "<$x>" "<$y>"
diff <(git log --since=2019-12-25 --until=2019-12-26 | sha1sum) <(git log --since="2019-12-25 $x" --until="2019-12-26 $y" | sha1sum) | wc -l
done
done
x <> y <> --> 0
x <> y <00:00:00> --> 4
x <> y <23:59:59> --> 4
x <00:00:00> y <> --> 4
x <00:00:00> y <00:00:00> --> 4
x <00:00:00> y <23:59:59> --> 4
x <23:59:59> y <> --> 4
x <23:59:59> y <00:00:00> --> 4
x <23:59:59> y <23:59:59> --> 4
$

Related

Keep text in place regardless output bash printf

This happens when numbers gets bigger...Just started with this mess.
Text being pushed around by bigger outputs...how do I contain this mess?
Accounts......: 5 Mail..........: 7
Banned........: 0 Pets..........: 1
Online........: 0 Tickets.......: 0
Guilds........: 1 Corpses.......: 0 PvP.......: 0
Members.......: 1 Characters....: 10 Gifts.....: 4 <-----HOWTO Reserve/Preserve spaces ?? ??
Should look like this:
Accounts......: 5 Mail..........: 7
Banned........: 0 Pets..........: 1
Online........: 0 Tickets.......: 0
Guilds........: 1 Corpses.......: 0 PvP.......: 0
Members.......: 1 Characters....: 10 Gifts.....: 4
Now this mess looks like this:
ch_count=$(mysql --defaults-extra-file="$sql_mycnf" -N --execute="SELECT count(*) FROM $db_characters.characters;"); &> /dev/null
cm_char="\033[0mCharacters\e[0;32m....:\033[0m $ch_count\e[31m"
line=" "
$cm_acco$line$cm_mail
$cm_bann$line$cm_pets
$cm_onli$line$cm_tick
$cm_guil$line$cm_corp$line$cm_pvps
$cm_memb$line$cm_char$line$cm_gifts
On another server there is same outputs but because they are smaller it looks fine:
Accounts......: 4 Mail..........: 0
Banned........: 0 Pets..........: 0
Online........: 0 Tickets.......: 0
Guilds........: 0 Corpses.......: 0 PvP.......: 0
Members.......: 0 Characters....: 2 Gifts.....: 0
Edit this line to make it work?
Is this correct place to begin?
cm_char="\033[0mCharacters\e[0;32m....:\033[0m $ch_count\e[31m"
Kill me.
Make 2 functions that will format the fields and use them:
dot_field() {
# todo Change implementation when field can be 2 words with a space in between
printf "%-14.14s:" "$1" | tr ' ' '.'
}
space_number() {
printf "%-7.7s" "$1"
}
printline() {
# Todo: add logic when only 4 parameters are given
echo " $(dot_field $1) $(space_number $2)$(dot_field $3) $(space_number $4)$(dot_field $5) $(space_number $6)"
}
printline "Guilds" 1 "Corpses" 0 "PvP" 0
printline "Members" 1 "Characters" 10 "Gifts" 4
printline "LongFieldName" 1 "High" 999999 "X" 2
EDIT: Adding colors.
You don't want to have your code full of escape codes for the colors. It depends on the full context how you would like to structure your color codes, I give an example for the limited context of the question. It should give you an idea how you can make something like this for yourself.
init_colors() {
reset=$(tput sgr0)
bold=$(tput bold)
black=$(tput setaf 0)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
magenta=$(tput setaf 5)
cyan=$(tput setaf 6)
white=$(tput setaf 7)
user_color=$bold
}
# colorstring reads from stdin and uses parameter 1 as an escape sequence
# with more parameters the first is used as a color, the other as the string to be modified
# It will set colors until the last space sequence
colorstring() {
case $# in
0) # invalid
echo "colorstring called without parameters"
;;
1)
sed -r "s/^.*[^ ]/$1&${reset}/"
;;
*)
color="$1"
shift
sed -r "s/^.*[^ ]/${color}&${reset}/" <<< "$#"
;;
esac
}
dot_field() {
# todo Change implementation when field can be 2 words with a space in between
printf "%-14.14s" "$1" | colorstring ${cyan} | tr ' ' '.'
# The : must be printed in a second statement when you don't want cyan dots.
printf ':'
}
space_number() {
printf "%-7.7s" "$1" | colorstring ${red}
}
printline() {
echo " $(dot_field $1) $(space_number $2)$(dot_field $3) $(space_number $4)$(dot_field $5) $(space_number $6)"
}
# init the color variables
init_colors
# Next echo not needed, just testing the new colorstring function
echo "$(colorstring ${blue} blue string) $(colorstring ${red} red car) $(colorstring ${white} white snow) $(colorstring ${yellow} yellow marker) $(colorstring ${cyan} cyan) "
printline "Guilds" 1 "Corpses" 0 "PvP" 0
printline "Members" 1 "Characters" 10 "Gifts" 4
printline "LongFieldName" 1 "High" 999999 "X" 2
As you may alredy know there are some spesial system sequinces
that controll output to terminal. This for example will turn text red '\e[31m'
and this will print text in certain column\line '\e[${LINE};${COLUMN}H'.
So we will use that. First i will create this 'data' array with "name value" pairs
to simulate your case.
data=(
"Accounts 5"
"Banned 10"
"Online 40"
"Guilds 4"
"Members 1"
"Mail 71"
"Pets 43"
"Tickets 0"
"Corpses 101"
"Characters 10"
"PvP 0"
"Gifts 4"
)
I'm using this table when working with text output so lets used it to
#--------------------------------------------------------------------+
#Color picker, usage: printf ${BLD}${CUR}${RED}${BBLU}"Hello!)"${DEF}|
#-------------------------+--------------------------------+---------+
# Text color | Background color | |
#-----------+-------------+--------------+-----------------+ |
# Base color|Lighter shade| Base color | Lighter shade | |
#-----------+-------------+--------------+-----------------+ |
BLK='\e[30m'; blk='\e[90m'; BBLK='\e[40m'; bblk='\e[100m' #| Black |
RED='\e[31m'; red='\e[91m'; BRED='\e[41m'; bred='\e[101m' #| Red |
GRN='\e[32m'; grn='\e[92m'; BGRN='\e[42m'; bgrn='\e[102m' #| Green |
YLW='\e[33m'; ylw='\e[93m'; BYLW='\e[43m'; bylw='\e[103m' #| Yellow |
BLU='\e[34m'; blu='\e[94m'; BBLU='\e[44m'; bblu='\e[104m' #| Blue |
MGN='\e[35m'; mgn='\e[95m'; BMGN='\e[45m'; bmgn='\e[105m' #| Magenta |
CYN='\e[36m'; cyn='\e[96m'; BCYN='\e[46m'; bcyn='\e[106m' #| Cyan |
WHT='\e[37m'; wht='\e[97m'; BWHT='\e[47m'; bwht='\e[107m' #| White |
#----------------------------------------------------------+---------+
# Effects |
#--------------------------------------------------------------------+
DEF='\e[0m' #Default color and effects |
BLD='\e[1m' #Bold\brighter |
DIM='\e[2m' #Dim\darker |
CUR='\e[3m' #Italic font |
UND='\e[4m' #Underline |
INV='\e[7m' #Inverted |
COF='\e[?25l' #Cursor Off |
CON='\e[?25h' #Cursor On |
#--------------------------------------------------------------------+
# Text positioning, usage: XY 10 10 "Hello World!" |
XY () { printf "\e[${2};${1}H${3}"; } # |
#--------------------------------------------------------------------+
# Print line, usage: line - 10 | line -= 20 | line "Hello World!" 20 |
line () { printf -v LINE "%$2s"; printf -- "${LINE// /$1}"; } # |
# Create sequence like {0..X} |
cnt () { printf -v _N %$1s; _N=(${_N// / 1}); printf "${!_N[*]}"; } #|
#--------------------------------------------------------------------+
There are all basic colors set as vars to easily insert in text and some
usefull functions like XY i'll use it to print text in serrtain position.
Lets set some vars
space_betwen=7 # space betwen columns
X=$space_betwen # starting X(column) position
Y=10 # starting Y(line) position
dot_string='...............: ' # dot string to simulate your output
dot_length=${#dot_string} # this will calculate the length of the dot string
Ok we are ready to go but first lets clear all text from terminal screen
clear
And now we can iterate through data and print text in 3 columns by 4 lines
for item in "${data[#]}"; {
((counter++)) # lets count items to know when start next column
read name value <<< $item # get naame and value from current item
XY $X $Y "$dot_string$RED$value$DEF" # print dot string and red value
XY $X $Y "$YLW$name$DEF" # name will be printed ower dots in yelow color
((Y++)) # go to next line by increasing Y value
# chek if we print 4 lines than set Y to start poosition and inc X to space_betwen+dot_length
((counter%4)) || { Y=10; ((X+=space_betwen+dot_length)); }
}
The final script will be like this
#!/bin/bash
data=(
"Accounts 5"
"Banned 10"
"Online 40"
"Guilds 4"
"Members 1"
"Mail 71"
"Pets 43"
"Tickets 0"
"Corpses 101"
"Characters 10"
"PvP 0"
"Gifts 4"
)
. ~/SCR/color # include color table
space_betwen=7 # space betwen columns
X=$space_betwen # starting X(column) position
Y=10 # starting Y(line) position
dot_string='...............: ' # dot string to simulate your output
dot_length=${#dot_string} # this will calculate the length of the dot string
clear
for item in "${data[#]}"; {
((counter++)) # lets count items to know when start next column
read name value <<< $item # get naame and value from current item
XY $X $Y "$dot_string$RED$value$DEF" # print dot string and red value
XY $X $Y "$YLW$name$DEF" # name will be printed ower dots in yelow color
((Y++)) # go to next line by increasing Y value
# chek if we print 4 lines than set Y to start poosition and inc X to space_betwen+dot_length
((counter%4)) || { Y=10; ((X+=space_betwen+dot_length)); }
}
XY 1 20 "$DEF" # one more time to move cursor down in the end
And the output will be like this

Plot graph using shell for total file count and date created

I want to create a histogram with total file count intervals of 50 on Y-axis and time created in weeks on X-axis (i.e if new files were created between week 1 and 2 and so on)
Something like
200, 150, 100 , 50 files created during a certain week
7, 14, 21, 28 days on Y-axis. Kind of lost on how to implement this. Any help is appreciated
Update: I am trying along these lines
find <dirname> -type f -ctime -1 -ctime -7 | wc -l
find <dirname> -type f -ctime +7 -ctime -14 | wc -l
Find the max number and use this as my X-axis upper limit. Then divide this number into equal intervals to plot my X-axis
This is a start using GNU awk for time functions (untested since you didn't provide concise, testable sample input that we could test against):
find "$1" -type f -printf '%T# %p\0' |
awk -v RS='\0' '
BEGIN {
nowSecs = systime()
}
{
fileName = gensub(/\S+\s+/,"",1)
fileModSecs = int($1)
fileAgeSecs = nowSecs - fileModSecs
fileAgeDays = int(fileAgeSecs / (24 * 60 * 60))
fileAgeWeeks = int(fileAgeDays / 7)
weekNr = fileAgeWeeks + 1
fileCnts[weekNr]++
numWeeks = (weekNr > numWeeks ? weekNr : numWeeks)
maxFileCnt = (fileCnts[weekNr] > maxFileCnt ? fileCnts[weekNr] : maxFileCnt)
print nowSecs, fileModSecs, fileAgeSecs, fileAgeDays, fileAgeWeeks, weekNr, fileName | "cat>&2"
}
END {
for (fileCnt=maxFileCnt; fileCnt>0; fileCnt--) {
for (weekNr=1; weekNr<=numWeeks; weekNr++) {
if (weekNr in fileCnts) {
char[weekNr] = "*"
}
printf "%s%s", char[weekNr], (weekNr<numWeeks ? OFS : ORS)
}
}
for (weekNr=1; weekNr<=numWeeks; weekNr++) {
printf "%s%s", weekNr, (weekNr<numWeeks ? OFS : ORS)
}
}
'
You need to figure out the details of the loops in the END section for printing the histogram but the above at least shows you how to get the count of files by week without calling find multiple times and hard-coding the number of days week by week.
Apologies being ksh instead of bash (bash level is near echo "Hello World") :)...
Would that do what you need ?
#!/bin/ksh
######################################
#
# statDirReport.sh
#
version="1.0"
# Andre Gelinas, 2018
#
######################################
#############
# Variables
#############
typeset -F2 SCALE
# Max value of X
X_SCALE=30
#############
# Main
#############
if [[ -n $1 ]]; then
DIRNAME=$1
else
print -n "Enter full path to stat : "; read DIRNAME
fi
if [[ ! -d $DIRNAME || ! -r $DIRNAME || ! -x $DIRNAME ]]; then
print "ERROR - Directory unusable - Exiting"
exit
fi
## Getting the data
CTIME1=1
CTIME2=0
for ((i=1;i<=4;i++)); do
CTIME2=$(($i*7))
FILE_COUNT[$i]=$(find $DIRNAME -type f -ctime +$CTIME1 -ctime -$CTIME2 | wc -l)
#To find late on the max amount
F_COUNT[${FILE_COUNT[$i]}]=${FILE_COUNT[$i]}
#
CTIME1=$CTIME2
done
#Doing some math
## Highest number of file
MAX_COUNT=${F_COUNT[-1]}
## Find the value of each tick
SCALE=$(($MAX_COUNT/$X_SCALE))
## Find the real length of the histogram for each week
## having the highest amount using full x scale (integer mathematics)
for ((i=1;i<=4;i++)); do
DATA_2_SCALE[$i]=$(((${FILE_COUNT[$i]}*$X_SCALE)/$MAX_COUNT))
done
# Getting the report
typeset -L2 Col1
typeset -L1 Col2
typeset -L$(($X_SCALE+5)) Col3
typeset -L5 Col4
Col1="Wk"
Col2=" "
Col3="Data"
Col4="Real"
clear
print "statDirReport v$version\tScale is #=$SCALE\n"
print "$Col1$Col2$Col3$Col4\n"
for ((i=1;i<=4;i++)); do
Col1=$i
Col2="|"
graph=""
Col4=${FILE_COUNT[$i]}
for ((j=1;j<=${DATA_2_SCALE[$i]};j++)); do
graph+="#"
done
Col3=$graph
print "$Col1$Col2$Col3$Col4"
done
Edit to modify to add dates as title for the histograms. Modify the last part, right after the "DATA_2_SCALE" loop, with :
#Setting the title of each histogram
## Finding how many sec since the beginning of time
TODAY_SEC=$(date +"%s")
## Finding real date for find range
SEC_PER_DAY=86400
lastDate=$(date -u -d #"$TODAY_SEC" +"%m/%d")
for ((i=1;i<=4;i++)); do
firstDate=$(date -u -d #"$(($TODAY_SEC-(7*$i*$SEC_PER_DAY)))" +"%m/%d")
WEEK[$i]=$firstDate" to "$lastDate" "
lastDate=$firstDate
done
# Getting the report
typeset -L15 Col1
typeset -L1 Col2
typeset -L$(($X_SCALE+5)) Col3
typeset -L5 Col4
Col1="Wk"
Col2=" "
Col3="Data"
Col4="Real"
clear
print "statDirReport v$version\tScale is #=$SCALE\n"
print "$Col1$Col2$Col3$Col4\n"
for ((i=1;i<=4;i++)); do
Col1=${WEEK[$i]}
Col2="|"
graph=""
Col4=${FILE_COUNT[$i]}
for ((j=1;j<=${DATA_2_SCALE[$i]};j++)); do
graph+="#"
done
Col3=$graph
print "$Col1$Col2$Col3$Col4"
done
Using feedgnuplot on a home directory:
dirname=~
e=0
for f in `seq 7 7 28` ; do
find "${dirname}" -type f -ctime +$e -ctime -$f | wc -l
e=$f
done 2> /dev/null |
feedgnuplot --terminal 'dumb 50,15' --with boxes --unset grid --exit
Output:
5500 +-+-----+-------+------+-------+-----+-+
5000 +-+ ********* + + + +-+
4500 +-+ * * ******** +-+
4000 +-+ * * * * +-+
3500 +-+ * * * * +-+
3000 +-+ * * * * +-+
2500 +-+ * ********* * +-+
2000 +-+ * * * * +-+
1500 +-+ * * * * +-+
1000 +-+ * + * + * + ********* +-+
500 +-+-********************************-+-+
0 1 2 3 4 5

How to add a single special character randomly anywhere inside a string? Bash

I have this script that generates a random character between 8-16. I am confused as to how I would add a single random special character from a bank [! # # $ % ^ & * ( ) _ + ] anywhere randomly inside this string?
if [ $# -eq 0 ] then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=(~ ! # # $ % ^ & * - +)
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
echo $str
exit 0
fi
teststring=foobarspam
specialchars='!##$%^&*()_+'
randomchar=${specialchars:RANDOM % ${#specialchars}:1}
randompos=$(( RANDOM % ( ${#teststring} + 1 ) ))
newstring=${teststring:0:randompos}${randomchar}${teststring:randompos}
You can use the following code.
#!/bin/bash
if [ $# -eq 0 ]; then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=('~' '!' '#' '#' '$' '%' '^' '&' '*' '-' '+')
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
A=$(echo $str|wc -c) ## To get the count of
P=$((RANDOM % $A)) ## To get a random position of where to insert the character.
I=$((RANDOM % 11)) ## To get a random index number of chars array
C=${chars[$#]}
echo $str | sed 's!^\(.\{'$P'\}\).!\1\'"$C"'!' ## Inserting the special character to string in defined position
exit 0
fi
Output:
$ for i in `seq 1 10`;do ./test1;done
j^eh8BmD2H
0B01^1AN6EVw
Wu2$LLTILuDN8fSV
e^90gmHjksDo
eB7wa\#fmwf
NVAtJkmfqx~
JaHvD%uyO3rB
ncFrgyyz~UkZ
q0LLRHUNATM8DL
X%ARcXgyC1Do
I am not sure what script language are you using. I wrote a solution for you using PHP. If PHP is not what you are using, you should be able to convert the same logic to other languages and get the same results.
<?php
//This is the original string where you want to add a random character to
$org_string = 'This is My original String';
//calculates the length of the string
$org_length = strlen($org_string);
//find a random position
$pos = rand(0, $org_length-1);
//concatenate the first part of the string, random character, the remaining string
$final = substr($org_string, 0, $pos) . getOne() . substr($org_string, $pos);
//print the final value
echo $final;
//return a random string
function getOne(){
//the following string is 12 characters in length. it is all available characters that you want to select from
$str = '!##$%^&*()_+';
//return a random character
return $str[rand(0, 11)];
}
?>

while loop variable reading issue

I have a text file a.txt like this:
1 1 a
2 b
4 4 d
Now I read that text file and feed it into a while loop:
cat a.txt | while read k l o
do
echo " ${k} ${l} ${o} "
if [ "${k}" == "${l}" ]; then
echo " success ; X: ${k} Y : ${l} Z : ${o} "
else
echo " failed ; X: ${k} Y : ${l} Z : ${o} "
fi
done
In my text file 2nd line first value is empty. That's why I'm getting y value in to x and z value in to y.
How can I handle such empty values and get all values printed at their correct positions?
why don't you just insert 0 for empty x value?
anyway you would need 3 values.. /bin/sh read command assigns the first value to the first name..

bc truncate floating point number

How do I truncate a floating point number using bc
e.g if I do
echo '4.2-1.3' | bc
which outputs 2.9 how I get it to truncate/use floor to get 2
Use / operator.
echo '(4.2-1.3) / 1' | bc
Dividing by 1 works ok if scale is 0 (eg, if you start bc with bc and don't change scale) but fails if scale is positive (eg, if you start bc with bc -l or increase scale). (See transcript below.) For a general solution, use a trunc function like the following:
define trunc(x) { auto s; s=scale; scale=0; x=x/1; scale=s; return x }
Transcript that illustrates how divide by 1 by itself fails in the bc -l case, but how trunc function works ok at truncating toward zero:
> bc -l
bc 1.06.95
[etc...]
for (x=-4; x<4; x+=l(2)) { print x,"\t",x/1,"\n"}
-4 -4.00000000000000000000
-3.30685281944005469059 -3.30685281944005469059
-2.61370563888010938118 -2.61370563888010938118
-1.92055845832016407177 -1.92055845832016407177
-1.22741127776021876236 -1.22741127776021876236
-.53426409720027345295 -.53426409720027345295
.15888308335967185646 .15888308335967185646
.85203026391961716587 .85203026391961716587
1.54517744447956247528 1.54517744447956247528
2.23832462503950778469 2.23832462503950778469
2.93147180559945309410 2.93147180559945309410
3.62461898615939840351 3.62461898615939840351
define trunc(x) { auto s; s=scale; scale=0; x=x/1; scale=s; return x }
for (x=-4; x<4; x+=l(2)) { print x,"\t",trunc(x),"\n"}
-4 -4
-3.30685281944005469059 -3
-2.61370563888010938118 -2
-1.92055845832016407177 -1
-1.22741127776021876236 -1
-.53426409720027345295 0
.15888308335967185646 0
.85203026391961716587 0
1.54517744447956247528 1
2.23832462503950778469 2
2.93147180559945309410 2
3.62461898615939840351 3
Try the following solution. It will truncate anything after the decimal point without a problem:
echo 'x = 4.2 - 1.3; scale = 0; x / 1' | bc -l
echo 'x = l(101) / l(10); scale = 0; x / 1' | bc -l
You can make the code a tad shorter by performing calculations directly on the numbers:
echo 'scale = 0; (4.2 - 1.3) / 1' | bc -l
echo 'scale = 0; (l(101) / l(10)) / 1' | bc -l
In general, you can use this function to get only the integer part of a number:
define int(x) {
auto s;
s = scale;
scale = 0;
x /= 1; /* This will have the effect of truncating x to its integer value */
scale = s;
return (x);
}
Save that code into a file (let's call it int.bc) and run the following command:
echo 'int(4.2 - 1.3);' | bc -l int.bc
The variable governing the amount of decimals on division is scale.
So, if scale is 0 (the default), dividing by 1 would truncate to 0 decimals:
$ echo '(4.2-1.3) / 1 ' | bc
2
In other operations, the number of decimals is calculated from the scale (number of decimals) of each operand. In add, subtract and multiplication, for example, the resulting scale is the biggest of both:
$ echo ' 4.2 - 1.33333333 ' | bc
2.86666667
$ echo ' 4.2 - 1.333333333333333333 ' | bc
2.866666666666666667
$ echo ' 4.2000 * 1.33 ' | bc
5.5860
Instead, in division, the number of decimals is strictly equal to th evalue of the variable scale:
$ echo 'scale=0;4/3;scale=3;4/3;scale=10;4/3' | bc
1
1.333
1.3333333333
As the value of scale has to be restored, it is better to define a function (GNU syntax):
$ echo ' define int(x){ os=scale;scale=0;x=x/1;scale=os;return(x) }
int( 4.2-1.3 )' | bc
2
Or in older POSIX language:
$ echo ' define i(x){
o=scale;scale=0;x=x/1;scale=o;return(x)
}
i( 4.2-1.3 )' | bc
2
You say:
truncate/use floor
And those are not the same thing in all cases. The other answers so far only show you how to truncate (i.e. "truncate towards zero" i.e. "discard the part after the decimal").
For negative numbers, the behavior is different.
To wit:
truncate(-2.5) = -2
floor(-2.5) = -3
So, here is a floor function for bc:
# Note: trunc(x) is defined as noted elsewhere in the other answers
define floor(x) {
auto t
t=trunc(x)
if (t>x) {
return t-1
} else {
return t
}
}
Aside:
You can put this, and other helper functions, in a file. For instance, I have this alias in my shell:
alias bc='bc -l ~/.bcinit'
And so whenever I run bc, I get all my utility functions from ~/.bcinit available by default.
Also, there is a good list of bc functions here: http://phodd.net/gnu-bc/code/funcs.bc
You may do something like this:
$ printf "%.2f\n" $(echo "(4530 / 4116 - 1) * 100" | bc -l)
10.06
Here I am trying to find the % change. Not purely bc though.

Resources