SED (regular expression) problem ---

Hello,

I would like to replace Line 187 of my file named run_example.

The original line is below, including the spaces:

  celldm(1)   = 6.00, 

I want it to become something like

  celldm(1)   = 6.05, 

or

  celldm(1)   = 6.10, 

where the number is stored in a variable called $bulksize . This variable increments properly in my for loop.

I tried doing this:

cat run_example | sed -e "187 s_  [a-z]*(1)   = _& $bulksize,_" > run_example 

Didn't work...

Thank you for your help!

hmm - couple of potential issues with

cat run_example | sed -e "187 s_  [a-z]*(1)   = _& $bulksize,_" > run_example

Firstly, by opening the file for read and write at the same time you are likely to simply zero it. You are better to output to a new file, or use sed or perl inline editting.

Taking a 5 line file:

#  cat run_example 
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,

Then something like:

#  export bulksize=6.10

#  perl -pi -e 'if ($. == 4) { s/\=.*/= $ENV{bulksize},/ };' run_example 

#  cat run_example 
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.10,
celldm(1)   = 6.00,

Will change line 4 in place (didn't want to make a 187 line file:-)   Just change the 4 to 187 for line 187.

HTH

1 Like

Thanks -

Actually, I didn't realize this would make a difference, but I have a parent directory called [myExamples] that contains my scripts (prep) and (run_example).

I have already made subdirectories of [myExamples], and I can run (prep) to copy (run_example) into each subdirectory.

(run_example) has a few lines that look similar to Line 187, plus a lot of other hulababoos...

The problem is to automatically replace Line 187 of (run_example) in each subdirectory, with a different value of $bulksize (see top message)...

Below is a snippet of (prep) -

bulksize=`expr 6.00` #This line works
half=$(echo "scale=2; $bulksize / 2" | bc) #This line works
for i in `ls -d */`; 
    do    
    CORRECTED LINE HERE
    half=$(echo "scale=2; $half + 0.05" | bc) # This line works
    bulksize=$(echo "scale=2; $half * 2" | bc) # This line works
done;

Hello, bluesmodular, and welcome to the forums.

Using ls to generate the for loop's list is often a poor approach. If there are any IFS characters (by default, space, tab, and newline) in the resulting filenames, they will be mangled. Often, when making use of some of ls' options (recursive listing, for example), this shortcoming is disregarded if troublesome filenames aren't expected. However, in this particular case, ls is completely unnecessary; you can generate a list of the necessary files with a safe, simple glob.

As for editing each file in place, you can do so with ed:

half=....
bulksize=....
for i in */run_example; do
    printf '187s/= [^,]*/= %s/\nwq\n' "$bulksize" | ed -s "$i"
    half=....
    bulksize=....
done

Regards,
Alister

1 Like

Thank you Alister!

Follow-up question - By similarly using printf and ed, how would I replace a line that contains only a number, e.g. 6.00, with another number stored in variable $bulksize or $half ?

I guess I don't understand all the parts in this regular expression
'187s/= [^,]*/= %s/\nwq\n'

I know 187 is the line number, the s after that is substitution, and ^, matches a comma in the beginning? Or anything that's not a comma? Not sure what the rest of it means... where can I find a good reference for this?

Thanks!!

For example i want to 6.line

# cat myfile
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 10.00,
celldm(1)   = 6.00,   
[root@sistem1lnx bin]# ./deg
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 6.00,
celldm(1)   = 10.10,
celldm(1)   = 6.00,
#!/bin/bash
mybulksize=0.10
mynum=$(sed = myfile |
sed -e '{N;}' -e 's/\n//'|
sed -n "/^6/ {p;q}"|
sed 's/.*= \(.*\),/\1/')
mynewvalue=$(echo "scale=2; $mynum+$mybulksize" | bc -l)
newline="celldm(1)   = $mynewvalue,"
sed -i "6c$newline" myfile
cat myfile

I do not understand the problem