Command to count the characters present in the variable - linux

I am trying to count the number of characters present in the variable. I used the below shell command. But I am getting error - command not found in line 4
#!/bin/bash
for i in one; do
n = $i | wc -c
echo $n
done
Can someone help me in this?

In bash you can just write ${#string}, which will return the length of the variable string, i.e. the number of characters in it.

Something like this:
#!/bin/bash
for i in one; do
n=$(echo $i | wc -c)
echo $n
done

Assignments in bash cannot have a space before the equals sign. In addition, you want to capture the output of the command you run and assign that to $n, rather than that statement which would probably just assign $i to $n.
Use the following instead:
#!/bin/bash
for i in one; do
n=`$i | wc -c`
echo $n
done

It can be as simple as that:
str="abcdef"; wc -c <<< "$str"
7
But mind you that end of line counts as a character:
str="abcdef"; cat -A <<< "$str"
abcdef$
If you need to remove it:
str="abcdef"; tr -d '\n' <<< "$str" | wc -c
6

Related

Unix Script loop through individual variables in a list and execute code

I have been busting my head all day long without coming up with a sucessfull solution.
Setup:
We have Linux RHEL 8.3 and a file, script.sh
There is an enviroment variable set by an application with a dynamic string in it.
export PROGARM_VAR="abc10,def20,ghi30"
The delimiter is always "," and the values inside vary from 1 to 20.
Inside the script I have defined 20 variables which take the values
using "cut" command I take each value and assign it to a variable
var1=$(echo $PROGARM_VAR | cut -f1 -d,)
var2=$(echo $PROGARM_VAR | cut -f2 -d,)
var3=$(echo $PROGARM_VAR | cut -f3 -d,)
var4=$(echo $PROGARM_VAR | cut -f4 -d,)
etc
In our case we will have:
var1="abc10" var2="def20" var3="ghi30" and var4="" which is empty
The loop must take each variable, test if its not empty and execute 10 pages of code using the tested variable. When it reaches an empty variable it should break.
Could you give me a hand please?
Thank you
Just split it with a comma. There are endless possibilities. You could:
10_pages_of_code() { echo "$1"; }
IFS=, read -a -r vars <<<"abc10,def20,ghi30"
for i in "${vars[#]}"; do 10_pages_of_code "$i"; done
or:
printf "%s" "abc10,def20,ghi30" | xargs -n1 -d, bash -c 'echo 10_pages_of_code "$1"' _
A safer code could use readarray instead of read to properly handle newlines in values, but I doubt that matters for you:
IFS= readarray -d , -t vars < <(printf "%s" "abc10,def20,ghi30")
You could also read in a stream up:
while IFS= read -r -d, var || [[ -n "$var" ]]; do
10_pages_of_code "$var"
done < <(printf "%s" "abc10,def20,ghi30")
But still you could do it with cut... just actually write a loop and use an iterator.
i=0
while var=$(printf "%s\n" "$PROGARM_VAR" | cut -f"$i" -d,) && [[ -n "$var" ]]; do
10_pages_of_code "$var"
((i++))
done
or
echo "$PROGRAM_VAR" | tr , \\n | while read var; do
: something with $var
done

How to count the number of occurences of a char in a string in Bash

This is the code:
#bash/bin
echo "Enter a sentence:"
read -e -a sentence
char="k"
echo "${sentence}" | awk -F"${char}" '{print NF-1}'
Problem:
It returns this error:
': not a valid identifier sentence -1
Sample Input
Enter a sentence:
thanks and okay
Sample Output
2
Question:
How can I fix this?
Just strip everything but $char, then count the results.
echo "Enter a sentence:"
read -e sentence
char="k"
filtered=${sentence//[^$char]/} # Delete anything *not* a $char
echo "${#filtered}" # Output the length of filtered
Using standard shell, you need a pair of external utilities instead bash's parameter substitution operator.
echo "$sentence" | tr -cd "$char" | wc -c
#bash/bin
OLDIFS=$IFS; IFS=$'\0' # change IFS for avoid issue with spaces
read -a sentence -p "Enter a sentence: "
IFS=$OLDIFS # IFS old value
char="k"
grep -o '.' <<< "$sentence" | grep "$char" | wc -l # first grep explode string characters, second grab character, wc count occurrences

Getting a specific line from a string where the line number I must get is stored in a variable?

I'm trying to get a specific line of a variable. The line I must get is stored in i. My code looks like this right now.
$(echo "$data" | sed '$iq;d')
It looks like I'm putting i in there wrong, Putting a number in for i works fine but $i gets me the entire string.
I haven't found a solution that works with a variable yet and I'm not too familiar with bash and would appreciate help,
Edit: a bit of context
i=5
data=$(netstat -a | grep ESTAB)
line=$(echo "$data" | sed "${i}p")
echo $line
Use sed -n "${i}p" instead.
Example:
i=4; seq 1 10 | sed -n "${i}p"
Output:
4
Bonus:
i=5
readarray -O 1 -t data < <(exec netstat -a | grep ESTAB) ## Stores data as an array of lines starting at index 1
line=${data[i]}
echo "$line"
# printf '%s\n' "${data[#]}" ## Prints whole data.
Here is way you can do this in BASH itself:
IFS=$'\n' arr=($data)
echo "${arr[$i]}"

Operation Precedence

I want to store the result of a command into an array variable. I'm having trouble because the command itself contains variables that must be resolved before its execution. For example:
for ((i=1; i<=4; i++)); do
NEXT=$(( i + 1 ))
MYARRAY[i]=$(cat $VARIABLE | uniq | sed -n '$NEXTp')
done
The "cat $VARIABLE" command is being processed correctly. The problem is with "$NEXT" substitution that is immediately followed by a "p" character. How can I force the script to resolve $NEXT variable before executing the command and store the results inside MYARRAY[i]?
Thanks.
The typical solution is: ${NEXT}p
Notice that what you are doing is fairly atypical. It is more usual to assign to an array using something like:
IFS='
'
MYARRAY=( $( < $VARIABLE uniq | sed -n 1,5p ))
This will assign MYARRAY[0], which your original code does not do, but it's not clear to me if that is intentional or an attempt to adjust the indexing. As always, UUOC is to be discouraged, and although uniq can take $VARIABLE as an argument, it's a good idiom to use the redirection so I'm using that in the example to demonstrate a simple way to eliminate UUOC in 99.9% of the cases it appears.
You could add the 'p' to NEXT before using it in the expression:
for ((i=1; i<=4; i++)); do
NEXT=$(expr $i + 1)
NEXT+='p'
MYARRAY[i]=$(cat $VARIABLE | uniq | sed -n $NEXT)
done
You can use script like this:
for ((i=1; i<=4; i++)); do
NEXT=$(expr $i + 1)
MYARRAY[i]=$(cat $VARIABLE | uniq | sed -n $NEXT'p')
done

Parsing a CSV string in Shell Script and writing it to a File

I am not a Linux scripting expert and I have exhausted my knowledge on this matter. Here is my situation.
I have a list of states passed as a command line argument to a shell script ( e.g "AL,AK,AS,AZ,AR,CA..." ). The Shell script needs to extract each of the state code and write it to a file ( states.txt) , with each state in one line. See below
AL
AK
AS
AZ
AR
CA
..
..
How can this be achieved using a linux shell script.
Thanks in advance.
Use tr:
echo "AL,AK,AS,AZ,AR,CA" | tr ',' '\n' > states.txt
echo "AL,AK,AS,AZ,AR,CA" | awk -F, '{for (i = 1; i <= NF; i++) print $i}';
Naive solution:
echo "AL,AK,AS,AZ,AR,CA" | sed 's/,/\n/g'
I think awk is the simplest solution, but you could try using cut in a loop.
Sample script (outputs to stdout, but you can just redirect it):
#!/bin/bash
# Check for input
if (( ${#1} == 0 )); then
echo No input data supplied
exit
fi
# Initialise first input
i=$1
# While $i still contains commas
while { echo $i| grep , > /dev/null; }; do
# Get first item of $i
j=`echo $i | cut -d ',' -f '1'`
# Shift off the first item of $i
i=`echo $i | cut --complement -d ',' -f '1'`
echo $j
done
# Display the last item
echo $i
Then you can just run it as ./script.sh "AL,AK,AS,AZ,AR,CA" > states.txt (assuming you save it as script.sh in the local directory and give it execute permission)

Resources