what is iteration count and byte count in hexdump? - linux

It was really confusing to deal with hexdump command in linux.
Basically I am trying to get the output from the /proc/device-tree.
I tried to use the hexdump but ended up with confusion.
My dts contains
vvn = <0 0 2 2 0 0>;
I got a proc node under /proc/device-tree.
I tried the following command.
hexdump -v -e '4/1 "%x" " "' vvn ; echo
0000 0000 0002 0002 0000 0000
hexdump -v -e '1/4 "%x" " "' vvn ; echo
0 0 2000000 2000000 0 0
hexdump -v -e '4/1 "%x "' vvn ; echo
0 0 0 00 0 0 00 0 0 20 0 0 20 0 0 00 0 0 0
I got different output, I thought all will produce the same output.
Can anyone please explain me how to use the iterationcount and bytecount of the hexdump and what it's for and How to use the format too?

Iteration count controls how may times the format will be repeated.
Byte count indicates how many byte will be format for each iteration.
Format string is the same as that of printf.
'4/1 "%x" " "': iteration for 4 times: in each time, format 1 byte with "%x", and when the iteration finished, insert " ".
'1/4 "%x" " "': iteration for 1 time: in each time, format 4 byte with "%x", and when the iteration finished, insert " ". This is equal to '1/4 "%x "'
'4/1 "%x "': iteration for 4 times: in each time, format 1 byte with "%x "; when iteration finished, eats the last space, insert nothing.
I do know why hexdump eats the last space :(.

Related

SAS loop through 56 character string extract every two characters

Have a couple million records with a string like
"00 00 01 00 00 01 00 01 00 00 00 00 01 01 00 01 00 00 00 00 01"
String has a length of 56. All positions are filled with either a 0 or a 1.
My job is parse the string of each record every two positions
(there are no spaces, that is just for clarification).
If there is a 1 in position two that means increment var1 +1
If there is ALSO a 1 in position four, (don't care about leading "0"'s
in position 1/3/5/9...55, etc.) increment var2 + 1, up to 28 variables.
The entire 56 len string must be parsed every two characters. Potentially
there could be 28 variables that have to be incremented, (but not realistic,
most likely there is only five or six) which could be found in any part of the
string, beginning to end (as long as they are in position 2/4/6/8 up to 56, etc.)
This is what my boss gave me:
if substr(BigString,2,1)='1' then var1+1;
OK. Fine.
A) There are 27 more places to evaluate in the string.
B) there are a couple million records.
28 nested if then do loops doesn't sound like an answer (all I could think of). At least not to me.
Thanx.
I think the author is trying to look for an do-loop method. So my suggest is macro %do or array statment in data step.
data _null_;
text = '000001000001000100000000010100010000000001';
y = length(text);
array Var[28];
do i = 1 to dim(Var);
Var[i] + (substrn(text,i*2,1)='1');
put i = Var[i]=;
end;
run;
Kind of easy, isn't is?
Array the variables that are to be potentially incremented according to string. A DO loop can examine each part of the string and conditionally apply the needed increment.
The SUM statement <variable>+<expression> means the variable's value is automatically retained from row to row.
Due to the nature of retained variables, you might want only the final var1-var28 values at the last row in the data. The question does not have enough info regarding what is to be done with the var<n> variables.
Example:
Presume string is named op_string (op for operation). Utilize logical evaluation result True is 1 and False is 0
data want(keep=var1-var28);
set have end=done;
array var var1-var28;
do index = 1 to 28;
var(index) + substr(op_string, 2 * index) = '1'; * Add 0 or 1 according to logic eval;
end;
if done; * output one row at the end of the data set;
run;
Use COUNTC() to count the number of 1's in the string then.
data want;
set have;
value = countc(op_string, '1');
run;
if I understood the problem well, this could be the solution:
EDITED 2. solution:
/* example with same row*/
data test;
a="00000100000100010000000001010001000000000100000000011110";output;
a="10000100000100010000000001010001000000000100011100011101";output;
a="01000100000100010000000001010001000000000100000001000000";output;
a="10100100000100010000000001010001000000000111111111111110";output;
a="01100100000100010000000001010001000000000101010101010101";output;
a="00000100000100010000000001010001000000000100001100101010";output;
run;
/* work by rows*/
%macro x;
%let i=1;
data test_output(drop=i);
set test;
i=1;
%do %while (&i<=56);
var&i.=0;
var&i.=var&i.+input(substr(a,&i,1), best8.);
%let i=%eval(&i.+1);
%end;
run;
%mend;
%x;
/* results:
a var1 var2 var3 var4 var5 var6 var7 . .
00000100000100010000000001010001000000000100000000011110 0 0 0 0 0 1 0 .......
10000100000100010000000001010001000000000100011100011101 1 0 0 0 0 1 0 .......
01000100000100010000000001010001000000000100000001000000 0 1 0 0 0 1 0 .......
10100100000100010000000001010001000000000111111111111110 1 0 1 0 0 1 0 .......
01100100000100010000000001010001000000000101010101010101 0 1 1 0 0 1 0 .......
00000100000100010000000001010001000000000100001100101010 0 0 0 0 0 1 0 .......
*/

How do I generate random numbers in 3 lines - Linux Shell Script

I would like to write a code that can generate 3 rows of 6 random numbers spaced out, which shuffle after a given time (0.5 seconds), and no new rows are created, basically 6 random numbers keep generating in 3 rows.
The code I have so far is:
echo " "
echo " "
echo " "
for i in {1..5};
do
for i in {1..1};
do
echo -ne " $(($RANDOM % 100)) $(($RANDOM % 100)) $(($RANDOM % 100)) $(($RANDOM % 100)) $(($RANDOM % 100)) $(($RANDOM % 100))\r"
done
sleep 0.5
done
However, when I try to add the second and third row to this, it doesn't seem to work the way I want it. A sample output could look like:
45 88 85 90 44 22
90 56 34 55 32 45
58 99 42 10 48 98
and between these numbers, new ones will generate, keeping only 6 columns and 3 rows. I have tried making matrix too but it didn't work for me.
I don't know if you have it finish, but continuing on from the comment, I would fill an indexed array with random values between 1-100, e.g.
#!/bin/bash
for ((i = 0; i < 18; i++)); do ## fill array with random values
a[i]=$(($RANDOM % 100 + 1))
done
What you would then want is a function you could call, passing the number of values in each row (so you can output a '\n' after those digits print) and then the array values as arguments to the function to read into a local array within the function (of course, you can just use the original array without worrying about passing elements as arguments, but I prefer using local values within function to preserve values in other scopes unchanged. For that your print function could be something like:
## function to print array in shuffled order, using tput for cursor control
prnarray() {
local n=$1
local al=( ${#:2} )
local c=0
for i in $(shuf -i 0-$((${#al[#]} - 1))); do
[ "$c" -gt '0' -a $((c % n)) -eq '0' ] && printf "\n"
printf " %3d" "${al[i]}"
((c++))
done
printf "\n"
tput cuu 6 ## tput is used for cursor control to move back to top
}
Then you really don't need much else bu a loop to print the array, sleep for some period of time and then call prnarray again to overlay the output with a new shuffle. e.g.
tput sc ## save cursor position
## call prnarray 3 times with 5 sec. delay between displays
declare -i c=0
while (( c < 3 )); do
prnarray 3 ${a[#]}
((c++))
sleep 5
done
tput rc ## restore cursor position
Example Use/Output
The array will print in the same spot every 5 seconds with the same elements shuffled to different positions within the array.
$ sh randomshuf.sh
33 30 34
86 98 48
94 89 80
50 57 34
11 45 57
80 42 22
Give it a shot and let me know if you have any questions.
Note: to make it 3x6 change the lines:
tput cuu 3
and
prnarray 6 ${a[#]}
With those changed your output would resemble:
$ sh randomshuf.sh
85 9 45 14 18 16
6 59 43 19 29 58
7 89 18 72 29 29
I would recommend you to avoid using the shell for this. The shell is great for automating system administration tasks - e.g interact with files, directories, shell commands -, but it is also great to keep people away from learning a 'real' and most powerful programming language.
python, ruby or perl can help you out.
if all you have is a hammer, everything looks like a nail.
e.g ruby
def print_random_numbers(num)
random_numbers = []
num.times do |n|
random_numbers << rand(100)
end
puts random_numbers.join(' ')
puts
end
while true
3.times do
print_random_numbers(6)
end
sleep 0.5
end
I'm not sure whether I really understand your problem, but:
This gets you 6 numbers taken at random from the range 1-100
numbers=$(shuf -i 1-100 -n 6)
echo $numbers
The numbers are selected without repetition. If you want repetition, use -r.
This gives you a permutation of the numbers drawn before:
echo $numbers | tr ' ' '\n' | shuf | xargs echo

Finding most significant bit in linux

I am working on raspberry pi, for the command :
char-write-req 0x0011 e00000e0
I am getting ouput1 as:
12 57 7e 35 2d 49
Similarly,
char-write-req 0x0011 e00100e1
output2 is:
23 45 76 3e 66 2d
In a similar way I am getting output for different commands, now I want to check for MSB and pass that bit in switch case i.e I want "1" from 12 of ouput1 and "2" from 23 of output2 and generate a switch case for that.
How can i do this?
Use cut -c 1 to get the first character from the output:
char-write-req 0x0011 e00000e0 | cut -c 1
For the case you use:
case `char-write-req 0x0011 e00000e0 | cut -c 1` in
1) echo "something" ;;
2) echo "something else" ;;
esac

How to use hexdump to show charaters in different presentations at the same time

I am counting the number of characters of files and directory names of an entire directory.
find . -printf "%f/n" | sed 's/./&\n/g' | sort | uniq -c
Output:
234 _
162 /
341 .
342 0
156 1
217 2
99 3
...
But I need also a list of decimal, hex and normal representation at the same time of the found characters:
Example:
066 0x42 'A'
...
090 0x5A 'Z'
I have tried hexdump with different format options but this didn't work for me.
Can it be done with hexdump ?
This is my implementation after your answer:
find . -printf "%f\n" | sed "s/./&\n/g" | sort | uniq | tr -d '\n' | hexdump -v -e '/1 "%03d "' -e '/1 "0x%02X "' -e '/1 "<%c>\n"'
Output:
060 0x3C <<>
062 0x3E <>>
058 0x3A <:>
063 0x3F <?>
046 0x2E <.>
097 0x61 <a>
098 0x62 <b>
099 0x63 <c>
100 0x64 <d>
101 0x65 <e>
069 0x45 <E>
102 0x66 <f>
104 0x68 <h>
072 0x48 <H>
105 0x69 <i>
108 0x6C <l>
109 0x6D <m>
110 0x6E <n>
078 0x4E <N>
111 0x6F <o>
195 0xC3 <�>
182 0xB6 <�>
...
Can it be done with hexdump?
Yes:
find . -printf "%f/n" |
hexdump -v -e '/1 "%03d "' -e '/1 "0x%02X "' -e '/1 "%c\n"'
See examples at the end of the hexdump man page.
An alternative to hexdump/hd is xxd. xxd can covert to hex and back. But I warn you with 32bit data and XOR I noticed an error I was getting 46 instead of 41. Also theres an option for uppercase and lowercase hex and out the default is BIG ENDIAN but theres a LITTLE ENDIAN ooption and remember the output is a char string and not the HEX equivalent.
I think the hexdump -C command is what you are looking for see man hexdump or man xxd.
PS> #Dummy00001 what does hexdumps "/1" do? I get the same result if I omit it
#ebart why is there a 'g' character in your sed script replacment operation replaces each char with \n at the end of line(&): "s/./&\n/g"
From link below:
The X/X format is called a count specifier, so 2/4 means 2 instances of a 4 byte (32 bit) value. The %08x format means output the value as an 8 digit hexadecimal number with leading zeros.
This command is not the answer to your question but shows how hexdump formatting is done:
hexdump -s 446 -n 64 -v -e '1/1 "%02x" 3/1 " %3d" 1/1 " %02x" 3/1 " %3d" 2/4 "

Linux: Formatting stream (pipe) output with column? (undetermined file size)

I would like to format text content that I am getting as a stdout stream using column, but I fail. For instance, using a single line, all works fine:
$ echo "1 12 123 1234 1 12 123 1234 " | column -t
1 12 123 1234 1 12 123 1234
.. however, if I try to simulate an "endless" stream:
$ while true; do echo "1 12 123 1234 1 12 123 1234 "; sleep 1; done | column -t
^C
... there is simply no response, until one exits with Ctrl-C.
(Note that the while thing is just meant to simulate reading an endless stream from a device, as in 'cat /dev/ttyUSB0')
This leads me to believe that, even if column by default should accept standard input, it needs a "complete" and finished file (that is, with a determined file size) in order to work; and in the case of an "endless" stream, that is not the case - so it never outputs anything.
Any suggestion on how I could achieve column formatting in this context? EDIT: Doesn't necesarily have to be the column program; anything else that formats text into columns would be fine (but I'm afraid, for instance awk also needs a complete file)...
Thanks in advance,
Cheers!
I, too, found column disappointing in its inability to stream, and sdaau's code in its inability to measure my columns. So here's a fix for both those problems. Maybe not terribly efficient, but it's just for debugging, anyway. I have it in my ~/bin folder as pcol (be sure to chmod +x it):
#!/usr/bin/env python
import sys
sep = ','
gutter = 2
for arg in sys.argv:
if arg.startswith('-s'):
sep = arg[2:]
elif arg.startswith('-g'):
gutter = int(arg[2:])
widths = []
while True:
raw = sys.stdin.readline()
line = raw.strip('\0').strip('\n')
vals = line.split(sep)
if len(vals) > len(widths):
widths = [0] * len(vals)
widths = [max(len(val) + gutter, width) for val, width in zip(vals, widths)]
metaformat = '%%%ds' * len(widths)
format = metaformat % tuple(widths)
print format % tuple(vals)
There is no response because your second command creates an infinite loop and then asks that once done, the result be piped to column -t. Since the loop will never terminate, column -t doesn't do anything. I'm not sure what you're trying to accomplish, but a variation of 2nd command that does produce output at one second intervals (which is what I'm assuming you want) is this:
while true; do echo "1 12 123 1234 1 12 123 1234 " | column -t; sleep 1; done
EDIT:
I see now what you're doing. For your situation, you could use sed to replace the spaces with tabs, which would automatically align your numbers to previous previous lines as long as number of digits doesn't exceed tab size:
echo "1 12 123 1234 1 12 123 1234 " | sed 's/ /\t/g'
OK, thanks to responses here, I managed to cook up a python script that will do that; obviously, you have to know (and enter in the script) the format of the columns a-priori; here's the script, columnizeline.py:
#!/usr/bin/env python
import sys;
#below no work:
#print sys.stdin;
#for line in sys.stdin:
# sline=line.split(' ')
# print sline
while 1:
next = sys.stdin.readline()
ns = next.strip('\0').split(' ') # remove null char
ns.pop() # remove the last entry in the list, it is '\n'
#~ nextf = "%4s %4s %4s %4s %4s %4s %4s %4s" % (ns[0], ns[1], ns[2], ns[3], ns[4], ns[5], ns[6], ns[7])
nextf=""
nsc = ns[0:6] # first 6 elements only
for nsi in nsc:
nextf = "%s%5s" % (nextf, nsi)
print nextf
... and here is a little test:
$ while true; do echo "1 12 123 1234 1 12 123 1234 "; sleep 1; echo "100 1 123 12 1 12 123 1234 "; sleep 1; done | ./columnizeline.py
1 12 123 1234 1 12 123 1234
100 1 123 12 1 12 123 1234
1 12 123 1234 1 12 123 1234
100 1 123 12 1 12 123 1234
1 12 123 1234 1 12 123 1234
100 1 123 12 1 12 123 1234
^CTraceback (most recent call last): [...]
Cheers!

Resources