while loop variable reading issue - linux

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..

Related

How to convert result as Integer in bash

when I do
$ ls | wc -l
703
It gave me the result 703, I want to print 702 (703-1)
How can I do it in bash?
You can use arithmetic expansion:
result=$(( $(ls | wc - l) - 1))
or just ignore one of the files
result=$(ls | tail -n+2 | wc -l)
Note that it doesn't work if filenames contain the newline character; use ls -q to get one filename per line in such a case. This applies to the first solution, too, if you're interested in the number of files and not the number of lines in their names.
(Cheeky answer) Remove one line from the output before counting :D
ls | sed '1d' | wc -l
How to convert result as Integer in bash
#choroba has already answered this question and it should have solved OP's problem. However, I want to add more to his answer.
The OP's wants to convert the result into Integer but Bash doesn't have any data type like Integer.
Unlike many other programming languages, Bash does not segregate its variables by "type." Essentially, Bash variables are character strings, but, depending on context, Bash permits arithmetic operations and comparisons on variables. The determining factor is whether the value of a variable contains only digits.
See this for arithmetic operation in Bash.
See this for a best example to learn the untyped nature of Bash. I have posted the example below:
#!/bin/bash
# int-or-string.sh
a=2334 # Integer.
let "a += 1"
echo "a = $a " # a = 2335
echo # Integer, still.
b=${a/23/BB} # Substitute "BB" for "23".
# This transforms $b into a string.
echo "b = $b" # b = BB35
declare -i b # Declaring it an integer doesn't help.
echo "b = $b" # b = BB35
let "b += 1" # BB35 + 1
echo "b = $b" # b = 1
echo # Bash sets the "integer value" of a string to 0.
c=BB34
echo "c = $c" # c = BB34
d=${c/BB/23} # Substitute "23" for "BB".
# This makes $d an integer.
echo "d = $d" # d = 2334
let "d += 1" # 2334 + 1
echo "d = $d" # d = 2335
echo
# What about null variables?
e='' # ... Or e="" ... Or e=
echo "e = $e" # e =
let "e += 1" # Arithmetic operations allowed on a null variable?
echo "e = $e" # e = 1
echo # Null variable transformed into an integer.
# What about undeclared variables?
echo "f = $f" # f =
let "f += 1" # Arithmetic operations allowed?
echo "f = $f" # f = 1
echo # Undeclared variable transformed into an integer.
#
# However ...
let "f /= $undecl_var" # Divide by zero?
# let: f /= : syntax error: operand expected (error token is " ")
# Syntax error! Variable $undecl_var is not set to zero here!
#
# But still ...
let "f /= 0"
# let: f /= 0: division by 0 (error token is "0")
# Expected behavior.
# Bash (usually) sets the "integer value" of null to zero
#+ when performing an arithmetic operation.
# But, don't try this at home, folks!
# It's undocumented and probably non-portable behavior.
# Conclusion: Variables in Bash are untyped,
#+ with all attendant consequences.
exit $?

How to pipe multiple inputs into a python script via the shell?

I'm looking to input a few strings into a python script so I can do test on my computer not http://www.ideone.com. But the ways I'm doing it all combine the strings instead of making them into lines or separate lines.
My code for python is 0001.py
testCases = int(input())
Counter = 0
while Counter < testCases:
Line = str(input())
countTwo = 1
for i in range(int(len(Line)/2)):
if countTwo % 2 == 0:
print(Line[i], end='')
countTwo += 1
print('\n', end='')
Counter += 1
I'm trying to do something like echo '5' 'hello' 'hello' 'hello' 'hello' | python3 001.py
Try
echo -e "line1\nline2\nline3"
This works because programs take input line by line. This echo statement separates the inputs over lines so it functions like you want.
Editing now that you've provided your OS.
For Linux, this works (credit to #pteronewone who also answered):
$ echo -e "5\nhello\nhello\nhello\nhello\nhello" | python3 001.py
e
e
e
e
e
For Windows (leaving here for future reference), this is ugly and inefficient but works (Windows 7 cmd.exe shell):
C:\> (echo 5 & echo hello & echo hello & echo hello & echo hello & echo hello) | 001.py
e
e
e
e
e
(Not sure exactly what you're trying to accomplish, but that's what your script outputs.)
A few other suggestions:
Wrap the input() in a try/except. In your example you only included four "hello" but told it to expect five, so it tries to read a fifth input which results in an exception.
try:
Line = str(input())
except:
break
Use the integer division operator // so you don't need to cast from float back to int in your range().
for i in range(len(Line) // 2):

Printing IFS values from file

Script:
#!/bin/ksh
FILENAME=$1
while read RECORD VALUE
do
echo ${RECORD} ${VALUE} "X"
done <"$FILENAME"
input file:
A 1
B 2
The output of script:
X1
X2
If I remove from echo "x", e.g.
echo ${RECORD} ${VALUE}
I am getting
A 1
B 2
what is wrong?
Update:
If I do
echo "X" ${RECORD} ${VALUE}
it prints correctly:
X A 1
X B 2
and :
echo ${RECORD} "X"
also prints correctly, so i am guessing the issues is with VALUE that maybe contains return carriage symbol (as input file was created on windows)
adding this inside the loop:
VALUE=`echo $VALUE| tr -d '\r'`
solved the issue, if you have a better solution you are more than welcome.
There is a parameter expansion operator you can use to remove a character from the end of a value, if it is present.
VALUE=${VALUE%$'\r'}
This is handled in-shell, without needing to start a new process.

Bash, print 0 in terminal each time a non recognised argument is input

I have a bash program which extracts marks from a file that looks like this:
Jack ex1=5 ex2=3 quiz1=9 quiz2=10 exam=50
I want the code to execute such that when I input into terminal:
./program -ex1 -ex2 -ex3
Jack does not have an ex3 in his data, so an output of 0 will be returned:
Jack 5 3 0
how do I code my program to output 0 for each unrecognized argument?
If I understand what you are trying to do, it isn't that difficult. What you need to do is read each line into a name and the remainder into marks. (input is read from stdin)
Then for each argument given on the command line, check if the first part matches the beginning of any grade in marks (the left size of the = sign). If it does, then save the grade (right side of the = sign) and set the found flag to 1.
After checking all marks against the first argument, if the found flag is 1, output the grade, otherwise output 0. Repeat for all command line arguments. (and then for all students in file) Let me know if you have questions:
#!/bin/bash
declare -i found=0 # initialize variables
declare -i grade=0
while read -r name marks; do # read each line into name & marks
printf "%s" "$name" # print student name
for i in "$#"; do # for each command line argument
found=0 # reset found (flag) 0
for j in $marks; do # for each set of marks check for match
[ $i = -${j%=*} ] && { found=1; grade=${j#*=}; } # if match save grade
done
[ $found -eq 1 ] && printf " %d" $grade || printf " 0" # print grade or 0
done
printf "\n" # print newline
done
exit 0
Output
$ bash marks_check.sh -ex1 -ex2 -ex3 < dat/marks.txt
Jack 5 3 0

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)];
}
?>

Resources