Echo character based on variable value (linux) - linux

My aim is to echo a character, for example #, based on a value such as num=6 and it must print # 6 times on the screen.
Not sure how to get this.

You could do something like
printf '#%.0s' {1..6}
or, in the more general case,
printf '#%.0s' $(seq 1 $num)

printf "%*s" "$num" " " | tr " " "#"
or
yes '#' | head -"$num" | tr -d "\n"

Related

printf padding from left by number other that zero

I have a=10 var that I want to pad from left with integer 1 with 5 padding.
Output should be below:
11110
when Im doing:
printf "%05d\n" "${a}"
it gives me 00010.
As per bash printf man page, it supports only zero padding, so you can't directly use integer padding other than zero.
You can do by string printing or pad by manipulating
a=10
printf '%s\n' 111${a}
or
printf "% 5d\n" "10" | tr ' ' '1'
I think I would just:
printf "% 5d\n" "10" | tr ' ' '1'
fill with spaces and then substitute spaces for ones.
You may use this instruction:
printf "%5d" "$a" | sed 's/ /1/g'
It outputs:
11110

Converting user input to uppercase

I am attempting to create a program in Unix that accesses a data file, adding, deleting, and searching within the file for names and usernames. With this if statement, I am attempting to allow the user to search for data in the file by the first field.
All of the data in the file uses uppercase letters, so I first must convert any text the user input from lowercase to uppercase letters. For some reason, this code is not working with both converting to uppercase and searching and printing the data.
How can I fix it?
if [ "$choice" = "s" ] || [ "$choice" = "S" ]; then
tput cup 3 12
echo "Enter the first name of the user you would like to search for: "
tput cup 4 12; read search | tr '[a-z]' '[A-Z]'
echo "$search"
awk -F ":" '$1 == "$search" {print $3 " " $1 " " $2 }'
capstonedata.txt
fi
This: read search | tr '[a-z]' '[A-Z]' will not assign anything to variable search.
It should be something like
read input
search=$( echo "$input" | tr '[a-z]' '[A-Z]' )
and it is better to use parameter expansion for case modification:
read input
search=${input^^}
If you use Bash, you can declare a variable to convert to uppercase:
$ declare -u search
$ read search <<< 'lowercase'
$ echo "$search"
LOWERCASE
As for your code, read doesn't have any output, so piping to tr doesn't do anything, and you can't have a newline before the file name in the awk statement.
Edited version of your code, minus all the tput stuff:
# [[ ]] to enable pattern matching, no need to quote here
if [[ $choice = [Ss] ]]; then
# Declare uppercase variable
declare -u search
# Read with prompt
read -p "Enter the first name of the user you would like to search for: " search
echo "$search"
# Proper way of getting variable into awk
awk -F ":" -v s="$search" '$1 == s {print $3 " " $1 " " $2 }' capstonedata.txt
fi
Alternatively, if you want to use only POSIX shell constructs:
case $choice in
[Ss] )
printf 'Enter the first name of the user you would like to search for: '
read input
search=$(echo "$input" | tr '[[:lower:]]' '[[:upper:]]')
awk -F ":" -v s="$search" '$1 == s {print $3 " " $1 " " $2 }' capstonedata.txt
;;
esac
Awk is not shell (google that). Just do:
if [ "$choice" = "s" ] || [ "$choice" = "S" ]; then
read search
echo "$search"
awk -F':' -v srch="$search" '$1 == toupper(srch) {print $3, $1, $2}' capstonedata.txt
fi

in Shell, How to insert a substring if not found in string

I want changes_summary to always be in format <x> files changed, <y> insertion(+), <z> deletions(-) where <x> <y> and <z> are some numbers, but diffstat misses insertions and/or deletions part if <y> and/or <z> is zero, I tried to make it print as <x> files changed 0 insertion(+), 0 deletions(-) always, is there a better or easy way to do this? I would like to change $changes_summary variable so I can use it later part of the script.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat | tail -1`
if ! echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+)," " " "0 deletions(-)"}'
elif ! echo $changes_summary | grep -q "insertions" && echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " "0 insertion(+), "$4 " " $5 }'
elif echo $changes_summary | grep -q "insertions" && ! echo $changes_summary | grep -q "deletions" ; then
echo $changes_summary | awk '{print $1 " " $2 " " $3 " " $4 " " $5 "0 deletions(-)" }'
fi
Probably the closest you can get without some serious bash magic or an other language is something like the following.
changes_summary=`diff -ur ./dir1 ./dir2 | diffstat -s`
CC=$(echo "$changes_summary" | sed -n 's:\(.*[0-9]\+ .* changed\).*:\1:p')
II=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ insertions\?\).*:\1:p')
DD=$(echo "$changes_summary" | sed -n 's:.*\([0-9]\+ deletions\?\).*:\1:p')
echo "${CC}, ${II:-0 insertions}(+), ${DD:-0 deletions}(-)"
Sed strips out the message corresponding to each stat. The -n suppresses the normal output, p prints only if a match is found. If not, then CC, II, DD will be empty, in which case the ${II:-...} pattern substitutes a default value.
From man bash:
${parameter:-word} Use Default Values. If parameter is unset or null,
the expansion of word is substituted. Otherwise, the value of
parameter is substituted.
Note that keeping the (s) with s\? might be an overkill for you.
The other option is that in bash you can check for containment with [[ $a =~ "b" ]] and use your original approach. It spares you the greps at least and "b" here can also be regex if you drop the quotes.
if ! [[ "$changes_summary" =~ "insert" ]]; then
awk ...
fi
You can also find the =~ in man bash.

Deleting specific symbols inside file

I have a problem. I have a file in this format:
Hi / Tom /
Be / Nice /
...
And I need to delete "/" and " "(space) and sort it
Be Nice
Hi Tom
...
for sorted_word in $(for word in $(sed -e 's/\/ //g' path_to_file); do printf "%s\n" ${word}; done | sort); do printf "%s " ${sorted_word}; done ; printf "%s\n"
you can use tr command like
cat inputfile.txt | tr -s "\/" "" | tr " " "\n" | sort | tr "\n" " "

Unterminated string / Syntax Error with Bash

I'm trying to get the follow code to read in variables from the user; files to search, a search string, wanted whitespace for output and the amount of fields to be output.
First issue is with the AWK command. If I enter a valid white space such as " " (A single space" or "\t" I am given the Unterminated string and syntax error, which only occurs if I request more than one field to be output (otherwise no whitespace is added on).
Secondly GREP seems to be a bit picky when using the search string. I've had to add double quotation marks to the start and finish of the variable in order for the entire string to be used.
#!/bin/bash
#****************************************************
#Name: reportCreator.sh
#Purpose: Create reports from log files
#Author:
#Date Written: 11/01/2013
#Last Updated: 11/01/2013
#****************************************************
clear
#Determine what to search for
printf "Please enter input file name(s): "
read inputFile
printf "Please enter your search query: "
read searchQuery
printf "Please enter the whitespace character: "
IFS= read whitespace
printf "Please enter the amount of fields to be displayed: "
read fieldAmount
#Add quotation marks to whitespace and searchQuery
whitespace=\""$whitespace"\"
searchQuery=\""$searchQuery"\"
#Declare variables
declare -i counter=0
declare -a fields[$fieldAmount]
declare -a fieldInsert[$fieldAmount]
#While loop for entering fields
while [[ "$counter" -ne "$fieldAmount" ]]
do
#Ask for field numbers
printf "Please enter number for required field $((counter+1)): "
read fields[$counter]
((counter++))
done
#Create function to add '$' before every field and the whitespace characters
function fieldFunction
{
for (( counter=0; counter <= ($fieldAmount-1); counter++ ))
do
fieldInsert[$fieldAmount]="$""${fields[$counter]}"
if (( counter!=($fieldAmount-1) ))
then
printf "${fieldInsert[*]}$whitespace"
else
printf "${fieldInsert[*]}"
fi
done
}
printf "%b\n"
tac $inputFile | grep "$searchQuery" | less #| awk '{print $(fieldFunction)}'
exit 0
Any help would be appreciated.
Grep doesn't understand quotes, so delete the line that adds them to $searchQuery.
Use double quotes instead of single quotes for awk, so $(fieldFunction) will expand.
Fixing this (as well as uncommenting the awk, of course), it works:
user#host 15:00 ~ $ cat script
#!/bin/bash
#****************************************************
#Name: reportCreator.sh
#Purpose: Create reports from log files
#Author:
#Date Written: 11/01/2013
#Last Updated: 11/01/2013
#****************************************************
clear
#Determine what to search for
printf "Please enter input file name(s): "
read inputFile
printf "Please enter your search query: "
read searchQuery
printf "Please enter the whitespace character: "
IFS= read whitespace
printf "Please enter the amount of fields to be displayed: "
read fieldAmount
#Add quotation marks to whitespace and searchQuery
whitespace=\""$whitespace"\"
#Declare variables
declare -i counter=0
declare -a fields[$fieldAmount]
declare -a fieldInsert[$fieldAmount]
#While loop for entering fields
while [[ "$counter" -ne "$fieldAmount" ]]
do
#Ask for field numbers
printf "Please enter number for required field $((counter+1)): "
read fields[$counter]
((counter++))
done
#Create function to add '$' before every field and the whitespace characters
function fieldFunction
{
for (( counter=0; counter <= ($fieldAmount-1); counter++ ))
do
fieldInsert[$fieldAmount]="$""${fields[$counter]}"
if (( counter!=($fieldAmount-1) ))
then
printf "${fieldInsert[*]}$whitespace"
else
printf "${fieldInsert[*]}"
fi
done
}
printf "%b\n"
tac $inputFile | grep "$searchQuery" | awk "{print $(fieldFunction)}"
exit 0
user#host 15:01 ~ $ cat file
foo two three four
foo two2 three2 four2
bar two three four
user#host 15:01 ~ $ bash script
Please enter input file name(s): file
Please enter your search query: foo
Please enter the whitespace character:
Please enter the amount of fields to be displayed: 2
Please enter number for required field 1: 4
Please enter number for required field 2: 2
four2 two2
four two
user#host 15:01 ~ $
Let's take a look at this section of code:
#Create function to add '$' before every field and the whitespace characters
function fieldFunction
{
for (( counter=0; counter <= ($fieldAmount-1); counter++ ))
do
fieldInsert[$fieldAmount]="$""${fields[$counter]}"
if (( counter!=($fieldAmount-1) ))
then
printf "${fieldInsert[*]}$whitespace"
else
printf "${fieldInsert[*]}"
fi
done
}
printf "%b\n"
tac $inputFile | grep "$searchQuery" | awk "{print $(fieldFunction)}"
It can be re-written more simply and robustly as (untested):
tac "$inputFile" |
awk -v fieldsStr="${fields[*]}" -v searchQuery="$searchQuery" -v OFS="$whitespace" '
BEGIN{ numFields = split(fieldsStr,fieldsArr) }
$0 ~ searchQuery {
for ( i=1; i <= numFields; i++ )
printf "%s%s", (i==1?"":OFS), $(fieldsArr[i])
print "\b"
}
'
I don't know why you need "tac" to open the file but I assume you have your reasons so I left it in.

Resources