Unix Scripting: date output and Newline(\n) not working - bash

i have 2 problems
whenever i ran the code below, it returns the 2nd date to 20, 30, 40, 50 and so on..
the "\n" won't work on my code, and i don't know why, i tried some tests, but for the code on the date , won't go to next (Answered)
Heres the code:
#!/bin/bash
echo "Testing Data entry for the 1st 7 days of the month"
min=01
max=7
while [ $min -lt 8 ]; do
echo -e "\n `date +"$min"%m%Y` $min \n" >> test.txt
let min=min+1
done
min=`date +%d -d "-1 month -$(($(date +%-d)-1)) day"`
cat test.txt
echo -e "Testing\nNewline"
echo -n > test.txt
My expected outcome shoud be:
01032014 1
02032014 2
03032014 3
04032014 4
05032014 5
06032014 6
07032014 7
but the outcome is this:
01032014 1
2032014 2
3032014 3
4032014 4
5032014 5
6032014 6
7032014 7

Try just using cat test.txt.
do not echo the result of cat.

You can replace your echo -e line with this to get new lines:
{ echo; date "+$min %m%Y $min"; echo; } >> test.txt

Related

bash script, to use a variable in a variable

In order to obtain the results of consecutive numbers, a bash script was created as follows.
However, the results did not come out as intended.
#!/bin/bash
test="i am $i"
for i in {1..10}
do
echo "$test"
done
result
sh test.sh
i am
i am
i am
i am
i am
i am
i am
i am
i am
i am
But the result I want is...
As shown below, how do we deal with the variables to get the results?
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
Use $i outside of the variable
#!/bin/bash
test="i am "
for i in {1..10}
do
echo $test $i
done
Also you can use ${i} inside of the variable
#!/bin/bash
for i in {1..10}
do
test="i am ${i}"
echo $test
done
The result is:
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
Or you can replace substr with anything you want inside.
For example
#!/bin/bash
test="I am SUBSTR"
for i in {1..10}
do
echo ${test/SUBSTR/$i}
done
When you have multiple variables, I know this solution:
#!/bin/bash
test="I am SUBSTR and STR2"
for i in {1..10}
do
o=${test/SUBSTR/$i}
echo ${o/STR2/$i*$i}
done
Using sed also can help
#!/bin/bash
test="I am SUBSTR and STR2"
for i in {1..10}
do
echo $test | sed -e 's/SUBSTR/'$i'/;s/STR2/'$i++'/'
done
You need to write a function in order to delay the evaluation.
#!/bin/bash
message () { echo "i am $1"; }
for i in {1..10}
do
message $i
done
Or the following, if you just want to craft the message.
#!/bin/bash
message () { echo "i am $1"; }
for i in {1..10}
do
test="$(message $i)"
echo "$test"
done
#!/bin/bash
test='i am $i'
for i in {1..10}
do
eval echo "$test"
done
or
#!/bin/bash
test='echo "i am $i"'
for i in {1..10}
do
eval "$test"
done
Example:
yanyong#master:~$ test='echo "i am $i"'; for i in {1..10}; do eval "$test"; done
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
References:
https://man7.org/linux/man-pages/man1/eval.1p.html

Print all numbers between two given numbers

I'm working on a Bash script which that takes in two integers and outputs all the numbers in between the two. It would look something like this:
Input:
bash testScript 3 10
3
4
5
6
7
8
9
10
This is some code that I wrote that I thought would work but I haven't had much luck getting it to work yet.
read myvar
read myvar2
while [ $myvar -le myvar2 ]
do
echo $myvar
myvar=$(($myvar+1))
//timer in-between numbers
sleep .5
done
Bash supports c style for loops using a double parenthesis construct:
$ for ((x=3; x<=10; x++)); { echo $x; }
3
4
5
6
7
8
9
10
Or, brace expansion:
$ for i in {3..6}; do echo $i; done
3
4
5
6
Problem with brace expansion is you need to use eval to use variables...
A common GNU utility for this is seq but it is not POSIX, so may not be on every *nix. If you want to write a similar function in Bash, it would look like this:
my_seq ()
# function similar to seq but with integers
# my_seq [first [incr]] last
{
incr=1
start=1
if [[ $# -gt 2 ]]; then
start=$1
incr=$2
end=$3
elif [[ $# -gt 1 ]]; then
start=$1
end=$2
else
end=$1
fi
for ((x=start; x<=end; x+=incr)); { echo $x; }
}
Then call that with 1, 2 or 3 arguments:
$ my_seq 30 10 60
30
40
50
60
with brace expansion
$ echo {3..10} | tr ' ' '\n'
or for variables with eval
$ a=3; b=10; eval echo {$a..$b} | ...
or, if you have awk
$ awk -v s=3 -v e=10 'BEGIN{while(s<=e) print s++}'
Use positional parameters:
myvar=$1
myvar2=$2
while [ $myvar -le $myvar2 ]
do
echo $myvar
myvar=$(($myvar+1))
#timer in-between numbers
sleep .5
done
Output:
scottsmudger#ns207588:~ $ bash test 1 5
1
2
3
4
5
See http://www.tldp.org/LDP/abs/html/othertypesv.html
Your posted codes are not aligned properly, not sure if it's your actual codes. But only problem other than the alignment is you missed a $ for myvar2 in the while statment.
read myvar
read myvar2
while [ $myvar -le $myvar2 ]
do
echo $myvar
myvar=$(($myvar+1))
#//timer in-between numbers
sleep .5
done

format lines using Shell scripts

I have a list of shell scripts (that end with .sh) in a folder and I am trying to make a list of them, and the list should have two script names (separated by a space) in each line. I wrote the following script, but it does not work without showing any errors. I was hoping to get some help here:
file1=""
for file in $(ls ./*.sh); do
i=1
file1="$file1$file "
if [ $i -lt 3 ]; then
i=$(( i++ ))
continue
fi
echo "file1 is $file1" # expected $file1 is: scriptName1.sh scriptName2.sh
echo $file1 >> ScriptList.txt # save the two file names in the text file
file1=""
done
To get tab separated output:
ls *.sh | paste - -
The pr utility is handy for columnizing as well. It can split the data "vertically":
$ seq 10 | pr -2 -T -s" "
1 6
2 7
3 8
4 9
5 10
or "horizontally"
$ seq 10 | pr -2 -T -s" " -a
1 2
3 4
5 6
7 8
9 10
It's not a good idea to set i=1 everytime in your loop.
Try
ls -1 | while read a;
do
if [ -z $save ]; then
save="$a"
else
echo "$save $a"
save=""
fi
done

put rows of numbers into a column with shell script

I have a file with many lines, like
1 jfkdajfd 1 2 3 5
2 fkldfjld
3 fdkfloaf 9 10
4 fldfldkf
5 fdskf;ak 12 1 4
I want to get all the numbers and put them in a column in a file, like
1
2
3
5
9
10
12
1
4
how can I achieve this?
thanks
In your case, it looks like you can do this:
awk '{for (i=3;i<=NF;++i) {print $i}}'
This is assuming that all the numbers you want to print occur in column 3 or after.
cat file | while read line
do
for i in $(echo ${line})
do
isnumeric=$(echo ${i} | grep -q [0-9]; echo ${?})
if [ ${isnumeric} -eq 0 ]
then
echo ${i} >> outfile
fi
done
done
not bulletproof and not as elegant as the previously given solutions, but it shows what is being used for determining if this is a numeric or not.
while read num alpha rest; do
[[ "$rest" ]] && printf "%s\n" $rest # <-- variable is unquoted
done < filename

For Loop in Shell Script - add breakline in csv file

I'm trying to use a for loop in a shell script.
I am executing a command from a text file. I wish to execute each command 10 times and insert some stats into a csv file. After that command has been done, I want to start the next BUT put a line break in the CSV file after the first command that was done 10 times.
Is the following correct:
#Function processLine
processLine(){
line="$#"
for i in 1 2 3 4 5 6 7 8 9 10
do
START=$(date +%s.%N)
echo "$line"
eval $line > /dev/null 2>&1
END=$(date +%s.%N)
DIFF=$(echo "$END - $START" | bc)
echo "$line, $START, $END, $DIFF" >> file.csv 2>&1
echo "It took $DIFF seconds"
echo $line
done
}
Thanks all for any help
UPDATE
It is doing the loop correctly, but I can't get it to add a line break after each command is executed 10 times.
processLine()
{
line="$#"
echo $line >> test_file
for ((i = 1; i <= 10 ; i++))
do
# do not move to the next line
echo -n "$i," >> test_file
done
# move to the next line: add the break
echo >> test_file
}
echo -n > test_file
processLine 'ls'
processLine 'find . -name "*"'
How about just adding a line "echo >> file.csv" after done? Or do you only want an empty line between each block of 10? Then you could do the following:
FIRST=1
processline()
{
if (( FIRST )) then
FIRST = 0
else
echo >> file.csv
fi
...rest of code...
}
Otherwise you might want to give an example of the desired output and the output you are getting now.
It looks reasonable. Does it do what you want it to?
You could simplify some things, e.g.
DIFF=$(echo "$END - $START" | bc)
could be just
DIFF=$((END - START))
if END and START are integers, and there's no need to put things in variables if you're only going to use them once.
If it's not doing what you want, edit the question to describe the problem (what you see it doing and what you'd rather have it do).

Resources