how to save arithmetic expression into a variable in shell? - macos

I want to save the number of lines minus 2 into a shell variable.
I have tried this:
eval a = wc -l meny1.xml | awk '{print $1}
tail a-2 meny1.xml >> tmp
for saving the number of line of a file and then decrease it by 2.
but it doesn't do the trick
how should I write this?

You could try something like:
$ export count=$((`wc -l < myfile` - 2))
$ echo $count
2
$ wc -l file
4

You can try something like
$ a=$(wc -l file | awk '{print $1-2}')
$ echo $a
3
$ wc -l file
5 file

Related

One line command with variable, word count and zcat

I have many files on a server which contains many lines:
201701010530.contentState.csv.gz
201701020530.contentState.csv.gz
201701030530.contentState.csv.gz
201701040530.contentState.csv.gz
I would like with one line command this result:
170033|20170101
169865|20170102
170010|20170103
170715|20170104
The goal is to have the number of lines of each file, just by keeping the date which is already in the filename of the file.
I tried this but the result is not in one line but two...
for f in $(ls -1 2017*gz);do zcat $f | wc -l;echo $f | awk '{print substr($0,1,8)}';done
Thanks in advance guys.
Just use zcat file | wc -l to get the number of lines.
For the name, I understand it is enough to extract the first 8 characters:
$ t="201701030530.contentState.csv.gz"
$ echo "${t:0:8}"
20170103
All together:
for file in 2017*gz;
do
lines=$(zcat "$file" | wc -l)
printf "%s|%s\n" "$lines" "${file:0:8}"
done > myresult.csv
Note the usage of for file in 2017*gz; to go through the files matching the 2017*gz pattern: this suffices, no need to parse ls!
Use zgrep -c ^ file to count the lines, here encapsulated in awk:
$ awk 'FNR==1{ "zgrep -c ^ " FILENAME | getline s; print s "|" substr(FILENAME,1,8) }' *.gz
12|20170101
The whole "zgrep -c ^ " FILENAME should probably be in a var (s) and then s | getline s.

Count of matching word, pattern or value from unix korn shell scripting is returning just 1 as count

I'm trying to get the count of a matching pattern from a variable to check the count of it, but it's only returning 1 as the results, here is what I'm trying to do:
x="HELLO|THIS|IS|TEST"
echo $x | grep -c "|"
Expected result: 3
Actual Result: 1
Do you know why is returning 1 instead of 3?
Thanks.
grep -c counts lines not matches within a line.
You can use awk to get a count:
x="HELLO|THIS|IS|TEST"
echo "$x" | awk -F '|' '{print NF-1}'
3
Alternatively you can use tr and wc:
echo "$x" | tr -dc '|' | wc -c
3
$ echo "$x" | grep -o '|' | grep -c .
3
grep -c does not count the number of matches. It counts the number of lines that match. By using grep -o, we put the matches on separate lines.
This approach works just as well with multiple lines:
$ cat file
hello|this|is
a|test
$ grep -o '|' file | grep -c .
3
The grep manual says:
grep, egrep, fgrep - print lines matching a pattern
and for the -c flag:
instead print a count of matching lines for each input file
and there is just one line that match
You don't need grep for this.
pipe_only=${x//[^|]} # remove everything except | from the value of x
echo "${#pipe_only}" # output the length of pipe_only
Try this :
$ x="HELLO|THIS|IS|TEST"; echo -n "$x" | sed 's/[^|]//g' | wc -c
3
With only one pipe with perl:
echo "$x" |
perl -lne 'print scalar(() = /\|/g)'

How to count lines in a file and add an arbitrary number to the result?

I have a file that contains 'x' lines in it.
I need to display the number of lines in such file and add 'y'.
I know that wc -l does the trick and displays 'x' as the output, how can it be so that the output would be 'x+y'?
You could do like this,
$ wc -l file
13 yi
$ y=12
$ wc -l file | awk -v var=$y '{print $1+var}'
25
You cannot change what wc -l gives, but you can write a function that does this example:
# with variables to match your x y example:
mylines()
{
x=$(cat $1 | wc -l) # this cat is to avoid the filename in output
y=$2
echo $(( $x + $y ))
}
Example usage: mylines somefile 19
will add 19 to the number of lines in myfile and display the sum

using cut command in bash [duplicate]

This question already has answers here:
Get just the integer from wc in bash
(19 answers)
Closed 8 years ago.
I want to get only the number of lines in a file:
so I do:
$wc -l countlines.py
9 countlines.py
I do not want the filename, so I tried
$wc -l countlines.py | cut -d ' ' -f1
but this just echo empty line.
I just want number 9 to be printed
Use stdin and you won't have issue with wc printing filename
wc -l < countlines.py
You can also use awk to count lines. (reference)
awk 'END { print NR }' countlines.py
where countlines.py is the file you want to count
If your file doesn't ends with a \n (new line) the wc -l gives a wrong result. Try it with the next simulated example:
echo "line1" > testfile #correct line with a \n at the end
echo -n "line2" >> testfile #added another line - but without the \n
the
$ wc -l < testfile
1
returns 1. (The wc counts the number of newlines (\n) in a file.)
Therefore, for counting lines (and not the \n characters) in a file, you should to use
grep -c '' testfile
e.g. find empty character in a file (this is true for every line) and count the occurences -c. For the above testfile it returns the correct 2.
Additionally, if you want count the non-empty lines, you can do it with
grep -c '.' file
Don't trust wc :)
Ps: one of the strangest use of wc is
grep 'pattern' file | wc -l
instead of
grep -c 'pattern' file
cut is being confused by the leading whitespace.
I'd use awk to print the 1st field here:
% wc -l countlines.py | awk '{ print $1 }'
As an alternative, wc won't print the file name if it is being piped input from stdin
$ cat countlines.py | wc -l
9
yet another way :
cnt=$(wc -l < countlines.py )
echo "total is $cnt "
Piping the file name into wc removes it from the output, then translate away the whitespace:
wc -l <countlines.py |tr -d ' '
Use awk like this:
wc -l countlines.py | awk {'print $1'}

count specific word in line in bash

i have variable such as "1,2,3,4"
i want to count of commas in this text in bash
any idea ?
thanks for help
This will do what you want:
echo "1,2,3" | tr -cd ',' | wc -c
Off the top of my head using pure bash:
var="1,2,3,4"
temp=${var//[^,]/}
echo ${#temp}
Isolate commas per line, count lines:
echo "$VAR"|grep -o ,|wc -l
very simply with awk
$ echo 1,2,3,4 | awk -F"," '{print NF-1}'
3
with just the shell
$ s="1,2,3,4"
$ IFS=","
$ set -- $s
$ echo $(($#-1))
3
A purely bash solution with no external programs:
$ X=1,2,3,4
$ count=$(( $(IFS=,; set -- $X; echo $#) - 1 ))
$ echo $count
3
$
Note: This destroys your positional parameters.
Another pure Bash solution:
var="bbb,1,2,3,4,a,b,qwerty,,,"
saveIFS="$IFS"
IFS=','
var=($var)x
IFS="$saveIFS"
echo $((${#var[#]} - 1))
will output "10" with the string shown.
echo '1,2,3' | grep -o ',' | wc -l

Resources