-1

Sample file:

11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, seq 1, length 64

In Python, it's easy to identify the number of field by using enumerate function. E.g.

>>> i = '11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, seq 1, length 64'
>>> 

Split the string

>>> i.split()
['11:34:21.590434', 'IP', '10.10.1.30', '>', '10.10.1.217:', 'ICMP', 'echo', 'reply,', 'id', '27948,', 'seq', '1,', 'length', '64']
>>> 

Put it on new variable, let say j

>>> j = i.split()
>>> 

Enumerate it

>>> for i in enumerate(j, 1): i
... 
(1, '11:34:21.590434')
(2, 'IP')
(3, '10.10.1.30')
(4, '>')
(5, '10.10.1.217:')
(6, 'ICMP')
(7, 'echo')
(8, 'reply,')
(9, 'id')
(10, '27948,')
(11, 'seq')
(12, '1,')
(13, 'length')
(14, '64')
>>> 

So, if I want to print out the source IP which is field number 3 with awk, it's so easy rather than to identify it manually with naked eyes.

wolf@linux:~$ awk '{print $3}' file.txt 
10.10.1.30
wolf@linux:~$ 

I know it's possible to do similar thing in Linux/Bash, I just can't figure it out yet.

Update

I know it's easy to get the number of column by using NF

wolf@linux:~$ awk '{ print NF }' file.txt
14
wolf@linux:~$ 

But what I want to achieve here is to identify each column and it's numbers. Probably something similar like Python enumerate output.

1

6 Answers 6

1

You can enumerate the fields using AWK:

awk '{ for (i = 1; i <= NF; i++) print i, $i }' file.txt

or with tr and nl:

tr ' ' '\n' < file.txt | nl

(Filter through head -n1 first if you want to stop at the end of the first line with tr; otherwise fields will be counted across lines.)

You can also find this out using Bash arrays (depending on IFS):

arr=($(head -n1 file.txt))
i=0
while [[ i -lt ${#arr[@]} ]]; do
    printf "%d %s\n" $((i+1)) "${arr[$i]}"
    ((i++))
done
0
1

With GNU awk for multi-char RS and \s shorthand for [[:space:]]:

$ awk -v RS='\\s+' '{print NR, $0}' file
1 11:34:21.590434
2 IP
3 10.10.1.30
4 >
5 10.10.1.217:
6 ICMP
7 echo
8 reply,
9 id
10 27948,
11 seq
12 1,
13 length
14 64

It assumes you only have 1 line in your input just like in the example in your question.

2
  • Thanks, but I did not get similar output ... wolf@linux:~$ awk -v RS='\\s+' '{print NR, $0}' file.txt 1 11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, 2 eq 1, length 64 wolf@linux:~$ echo $SHELL /bin/bash wolf@linux:~$ Commented Jan 31, 2021 at 17:03
  • Then you copy/pasted wrong, or you aren't using gawk as the answer says is required, or your input doesn't look like the line you posted. If you use the script I posted on the input you posted using gawk as I said is required then you WILL get the output I posted. Commented Jan 31, 2021 at 17:18
0

I guessed there are not any right solution rather than Stephen Kitt. but if you only need IP Addrerss you could use below

tr ' ' '\n' <<<'11:34:21.590434 IP 10.10.1.30 > 10.10.1.217: ICMP echo reply, id 27948, seq 1, length 64' | grep IP -A1 | grep -v IP
0

Hope this helps

$ tr ' ' '\n' < file.txt | nl
     1  11:34:21.590434
     2  IP
     3  10.10.1.30
     4  >
     5  10.10.1.217:
     6  ICMP
     7  echo
     8  reply,
     9  id
    10  27948,
    11  seq
    12  1,
    13  length
    14  64
$ 

or

$ read -ab < file.txt 
$ for c in ${b[*]}; do echo $c; done | nl
     1  11:34:21.590434
     2  IP
     3  10.10.1.30
     4  >
     5  10.10.1.217:
     6  ICMP
     7  echo
     8  reply,
     9  id
    10  27948,
    11  seq
    12  1,
    13  length
    14  64
$ 
0
0

Solution with sed

$ sed -n '/1/{s/ /\n/g;p}' < file.txt | nl
     1  11:34:21.590434
     2  IP
     3  10.10.1.30
     4  >
     5  10.10.1.217:
     6  ICMP
     7  echo
     8  reply,
     9  id
    10  27948,
    11  seq
    12  1,
    13  length
    14  64
       
$ 
0

grep out the fields and lay them one per line. Then number them with grep's -n option.

echo "....." |
grep -Po  '\S+' | grep -n ^ | sed 's/:/ /'

or

cat file.txt | grep -Po  '\S+' | grep -n ^ | sed 's/:/ /'

For perls more recent than 5.14.4

perl -lane '
  while (my($i,$e) = each @F) { print "$i $e"; }
' file.input

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.