wc -c and wc -m give the same output all the time? - linux

I am having the following doubt. wc -m and wc -c are always giving same output. I tried with floating point numbers also but the output is same for both the commands.
cat test | wc -m
541
cat test | wc -c
541

ASCII character takes byte. But UTF-8 local charaters takes 2 bytes.
echo -n "ŻÓŹŁŃĘ"|wc -m
6
echo -n "ŻÓŹŁŃĘ"|wc -c
12
P.S. You can wc -m test to save cat.

Related

extract syscall names from strace output

I use the following command to extract syscall names from strace output:
strace ls 3>&1 1>&2 2>&3 3>&- | grep -P -o '^[a-z]*(?=\()'
but this command also includes the ls output in the output.
how can I prevent that?
There are two options to strace that will help you get what you want:
-c will output a table of all system calls run by the command, together with the number of times they were called and CPU usage.
$ strace -c ls
Desktop Documents Downloads Music Pictures Public Templates Videos
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
31.07 0.000653 20 32 mmap
9.94 0.000209 20 10 mprotect
9.80 0.000206 12 16 read
8.28 0.000174 15 11 close
7.61 0.000160 16 10 fstat
6.90 0.000145 16 9 openat
2.47 0.000052 17 3 3 ioctl
...
The -o option will send strace's output to a file, so it won't get mixed in with your process's output.
The following will run the ls command, diverting its output to /dev/null, and will send strace's output to an awk script to extract the last column:
$ strace -o >(awk '$1 ~ /^-----/ { toprint = !toprint; next } { if (toprint) print $NF }') \
-c ls >/dev/null 2>/dev/null
mmap
mprotect
read
close
fstat
openat
ioctl
...
Finally I found a solution with the help of this link: http://mywiki.wooledge.org/BashFAQ/047
strace ls 2>&1 >/dev/null | grep -P -o '^[a-z]*(?=\()'
and a useful variant to count the syscalls:
strace ls 2>&1 >/dev/null | grep -P -o '^[a-z]*(?=\()' | sort | uniq -c | sort -nr
And a better solution using Mark Plotnick's answer:
strace -o >(grep -P -o '^[a-z]*(?=\()' | sort | uniq -c | sort -nr) ls &>/dev/null

Parsing a non-regular command output

I have the following output of iperf version 2 running on LEDE OS. I am trying to parse the output to get the number before the Mbits/sec which is the average throughput of the IPERF session. However, it seems the separation between each column does not match certain number of spaces nor tabs. In addition, the CSV format generated by iperf generates strange results, as a result I have to rely on the regular output of iperf. Any suggestion how to parse the output using either regular expression or awk command?
The iperf command:
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m
The output:
[ 3] 0.00-10.00 sec 1889 MBytes 1584 Mbits/sec 15114/0 0
2483K/3302 us
You can use grep for those.
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m | grep -o -E '\w+ Mbits/sec'
OR to be more accurate:
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m | grep -o -E '[0-9]+ Mbits/sec'
To get only the digits, you can use yet another regex,
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m | grep -Po '[[:digit:]]+ *(?=Mbits/sec)'
Above, [[:digit:]]+ and [0-9]+ are same and matches the digits in the line.
For FreeBSD grep in MacOS X, -P will not work. Instead use perl directly,
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m | perl -nle 'print $& if m{\d+ *(?=Mbits/sec)}'
You cat try to use awk tool :
iperf -c 10.0.0.7 -t 10 -i 0.1 -f m | awk -F 'MBytes' {'print $2'}
If this is iperf 2 then try -fb for bit/byte formatting. This format is easier to parse w/regular expressions as it's just a number. Man page is here.
`GENERAL OPTIONS
-f, --format [abkmgBKMG]
format to report: adaptive, bits, Bytes, Kbits, Mbits, Gbits, KBytes, MBytes, GBytes (see NOTES for more)`

Bash/SH, Same command different output?

$ cat a.sh
#!/bin/bash
echo -n "apple" | shasum -a 256
$ sh -x a.sh
+ echo -n apple
+ shasum -a 256
d9d20ed0e313ce50526de6185500439af174bf56be623f1c5fe74fbb73b60972 -
$ bash -x a.sh
+ echo -n apple
+ shasum -a 256
3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b -
And the last one is correct.
Why is that? and how to solve it?
Per POSIX, echo supports no options.
Therefore, when echo -n is run with sh, it outputs literal -n instead of interpreting -n as the no-trailing-newline option:
$ sh -c 'echo -n "apple"'
-n apple # !! Note the -n at the beginning.
Note: Not all sh implementations behave this way; some, such as on Ubuntu (where dash acts as sh), do support the -n option, but the point is that you cannot rely on that, if your code must run on multiple platforms.
The portable POSIX-compliant way to print to stdout is to use the printf utility:
printf %s "apple" | shasum -a 256

Perl Script to Grep Directory For String and Print

I would like to create a perl or bash script that will read keyboard input and assign a variable, perform a fixed string grep recursively within the current directory filled with Snort logs, and then automatically tcpdump the matched files, grep its output, and print the specified lines to the terminal. Does anyone have a good idea of how this should work?
Here is an example of the methodology I want from the script:
step 1: Read keyboard input and assign it to variable named string.
step 2 command: grep -Fr "$string"
step 2 output: snort.log.1470609906 matches
step 3 command: tcpdump -r snort.log.1470609906 | grep -F "$string" C-10
step 3 output:
Snort log
Here's some bash code that does that:
s="google.com"
grep -Frl "$s" | \
while IFS= read -r x; do
tcpdump -r "$x" | grep -F "$s" -C10
done
idk about perl but you can do it easily enough just in shell:
str="google.com"
find . -type f -name 'snort.log.*' -exec grep -FlZ "$str" {} + |
xargs -0 -I {} sh -c 'tcpdump -r "{}" | grep -F '"$str"' -C10'

how to capture the output of "sort -c" in linux

I am trying to capture the output of "sort -c" in linux. I tried redirecting it to a file, used tee command but both did not helped. Any suggestions ?
For example:
roor>cat db | sort -c
sort: -:319: disorder: 1842251880: aa bb bc dd ee
Following failed to give me output
roor>cat db | sort -c > fileName
roor>cat db | sort -c |tee fileName
Sample file:
>cat file
111 aa as sdasd
222 sadf dzfasf af
333 sada gvsdgf h hgfhfghfg
444 asdfafasfa gsdgsdg sgsg
222 asdasd fasdfaf asdasdasd
root>cat file |sort -c
sort: -:5: disorder: 222 asdasd fasdfaf asdasdasd
8>sort -c db 2> fileName
sort: extra operand `2' not allowed with -c
0>sort -c < file 2> result1.txt
sort: open failed: 2: No such file or directory
ANY ALTERNATE TO SORT -C would ALSO WORK FOR ME!!
If sort -c is producing an error, it sends that error to "standard error" (stderr), not to "standard output" (stdout).
In shell, you need to use special redirects to capture standard error.
sort -c inputfile > /path/to/stdout.txt 2> /path/to/stderr.txt
These two output streams are called "file descriptors", and you can alternately redirect one of them to the other:
sort -c inputfile > /path/to/combined.txt 2>&1
You can read more about how these work at tldp.org, in the Bash reference manual, the bash-hackers wiki and the Bash FAQ. Happy reading! :-D
other good alternative for '2>' is STDERR pipe
|&
cat db | sort -c -h |& tee >fileName
Some time it is very suitable when present STDIN, for example:
TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods -l app=pod >/dev/null ; done |& sort -u -h
or
TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods >>log1 ; done |& sort -u -h
sort -c has no output as you might expect:
[root#home:~] cat /etc/services | sort -c
sort: -:2: disorder: #
As described by the manpage, the -c argument simply checks whether a given file or input is sorted or not.
If you're trying to catch the message from the command, try redirecting the error stream (2), not the standard output (1):
cat file | sort -c 2>result.txt
sort -conly checks if the input is sorted. It does not performs any sorting.
See: man sort
Remove -c to sort the lines.
PS: It gives the "disorder" error because the file of yours isn't already sorted. On line 5, "222" appears after "444" on the previous line.
EDIT: I think I misunderstood.
To redirect the error to a file you must use 2>.
So, the command would become: roor>cat db | sort -c 2> fileName
EDIT2: You can simply use: sort -c db 2> fileName

Resources