Changing Line Number of a File

Example:
O o x
[

2 A X
3 B X
4 C X
5 D X
6 E Z
7 F Z
a b c 12d
]

What I would like to do is to rename the first column of the above file without affecting the format. The output should look like the following:

Output:
O o x
[

1 A X
2 B X
3 C X
4 D X
5 E Z
6 F Z

a 	b 	c 	12d

]

#! /bin/ksh

cd $HOME/lib/.Lee

#nl = no. of lines.
nl=`grep 'X' ex | wc -l`

#ln = line no.
ln=1
$1=NR
until [[ "$ln" = "$nl" ]]; do
awk '{$1 = NR; print}' ex
ln=ln+1
done

The above script affects the format and the results keep on and on and on.

awk -v no=1 ' /\[/,/\]/ { if ( $0 ~ "^[0-9]+ " ) { sub("^[0-9]+ ",no" ");no++}}; 1 ' filename

anbu can we have some awk code explanation..I am confused..but I like this topic

thanks in advance

/\[/,/\]/ { ... } This block is executed for lines between [ and ]

$0 ~ "[1]+ " Checks whether first field is a number

sub("[2]+ ",no" ") If above condition is true replace first field by the value in variable "no" and increment the variable "no"

1 which means true and prints the line


  1. 0-9 ↩︎

  2. 0-9 ↩︎

thanks for nice explanation..:slight_smile:

Thanks for the reply. I tried using the script you gave but showed the following messages:

awk: syntax error at source line 1
awk: bailing out at source line 1

So, I tried few other things but gave the same results. What I want to do exactly is to renumber only the first column where X are found.

Regards.

Use nawk to avoid this error.

Do you mean the X in third field? Then try this

nawk -v no=1 ' /\[/,/\]/ { if ( $0 ~ "^[0-9]+ " && $3 == "X"  ) { sub("^[0-9]+ ",no" ");no++}}; 1 ' filename

Try that:

awk '/^\[/,/^]/ { if ($3 == "X") $1=++line } 1' filename

Jean-Pierre.

Hello Anbu23!

The code you gave worked fine.

I tried to use similar nawk command to the file below but nothing happened.

nawk -v no=1 ' /M_I : \[/,/\]/ { if ( $1 ~ "^[0-9]+ " && $7 == "HI" ) { sub("^[0-9]+ ",no" ");no++}}; 1 ' filename

Contents of "filename":

D : [
# ===========

]

S : [
# ============

Nb_S_I : 5
S_I : [

# R_L "S_D"
56 "1-2x"
48 "1-2x"
40 "1-2x"
32 "1-2x"
24 "1-2x"

]

]

M_I : [
# ===========

# M_I B_T S_Nb C_Nb L_N P_Nb O M_I A_F D_F
4 X 9 1 2 4 HI 1 F F
5 F 2 1 4 0 HI 1 F F
6 F 4 1 6 0 HI 1 F F
10 L 1 1 8 4 HI 1 F F
]

The output should be as follows:

D : [
# ===========

]

S : [
# ============

Nb_S_I : 5
S_I : [

# R_L "S_D"
56 "1-2x"
48 "1-2x"
40 "1-2x"
32 "1-2x"
24 "1-2x"

]

]

M_I : [
# ===========

# M_I B_T S_Nb C_Nb L_N P_Nb O M_I A_F D_F
1 X 9 1 2 4 HI 1 F F
2 F 2 1 4 0 HI 1 F F
3 F 4 1 6 0 HI 1 F F
4 L 1 1 8 4 HI 1 F F

]

The field $1 can't contain a space that is a separator.
Change your test :

nawk -v no=1 ' /M_I : \[/,/\]/ { if ( $0 ~ "^[0-9]+ " && $7 == "HI" ) { sub("^[0-9]+ ",no" ");no++}}; 1 ' filename

The nawk program can be simplified:

nawk '/M_I : \[/,/\]/ { if ( $0 ~ /^[0-9]\+ / && $7 == "HI" ) $1 = ++no }; 1 ' filename

Jean-Pierre.

I have attached a sample file about the actual format of the lines I want its line numbers changed.

I used the following script to change the line numbers:

#! /bin/ksh

cd $HOME/lib
nawk -v no=1 ' /Marker_Item : \[/,/\]/ { if ( $5 == "HIGH" ) {sub($1,no);++no}}; 1 ' filename

As you noticed at the results, the alignment for lines 7, 8 and 9 has changed. Any ideas on how to realign it?

Thanks!

if you have Python, here's an alternative;

flag = False
num=1 # renaming counter
for line in open("file"):
    line = line.strip()
    if line.startswith("M_I : ["): flag = True
    if flag:        
        l = line.split()    
        try:
            if l[0].isdigit():
                l[0]=str(num)
                num+=1                 
        except:pass
        print " ".join(l)
    else:print line
    if line.startswith("]"):
        flag = False

output:

# ./test.py

D : [
# ===========



]


S : [
# ============

Nb_S_I : 5
S_I : [

# R_L "S_D"
56 "1-2x"
48 "1-2x"
40 "1-2x"
32 "1-2x"
24 "1-2x"

]

]


M_I : [
# ===========


# M_I B_T S_Nb C_Nb L_N P_Nb O M_I A_F D_F
1 X 9 1 2 4 HI 1 F F
2 F 2 1 4 0 HI 1 F F
3 F 4 1 6 0 HI 1 F F
4 L 1 1 8 4 HI 1 F F
]

I'm sorry ghostdog74 'coz I just use ksh shell.

Thanks for your help anyway.

nawk ' /Marker_Item : \[/,/\]/ { 
	if ( $5 == "HIGH" ) {
		str=$0;
		sub($1".*",$1,str);
		sub(" *"$1,sprintf("%*d",length(str),++no))
	}
}; 1 ' filename

anbu23, could you please explain the above script?

Thanks!

#! /bin/ksh

start=0
begin=0
while IFS=" " read first rest
do
    if [[ $first = *\[* ]] ; then
        begin=1
    elif [[ $first = *\]* ]] ; then
        begin=0
    fi;
    if [[ $begin == 1 ]]; then
        if [[ $first = *[123456789]* ]] ; then
            ((start=start+1))
            first=${start}
        fi;
            echo ${first}${IFS}${rest}

    elif [[ $begin == 0 ]]; then
        echo ${first}${IFS}${rest}
    fi;
done < input.file

sub($1".*",$1,str) Remove other than first field in str

sprintf("%*d",length(str),++no) Form a new string with the same format of first field. * is for field length and gets the value from length(str)

sub(" *"$1,sprintf("%*d",length(str),++no)) Substitute first field in $0 by the newly formed string.

The alignment for lines 7, 8 and 9 has changed because previously there was a two digit number. In above code we used length of first field and used sprintf to align it properly.

ANBU23, it works perfectly now. Thanks for all the help.

And to aigles, ghostdog74 and vino, thank you, too, for your suggestions.