MrEtArn
MrEtArn

Reputation: 325

replace a word in a specific location

I want to run a program while scanning a range of parameters and I need to replace a word in a specific location without matching any pattern

for example my input file contains the following lines:

...  
coords xyz  
O 0.0 0.0 0.0  
H 1.0 1.0 0.0  
H 1.0 -1.0 0.0  
...  

I want substitute the 3rd word in the 66th line (in this example "-1.0") with a different ($i) value in each iteration

I know I can maintain a original_input file, do a pattern search and output it to a Input file each time :

sed  "6s/-1.0/$i/" original_input > Input 

but I'm looking for a in-place substitute while the match pattern is continuously changing

Upvotes: 0

Views: 86

Answers (2)

MrEtArn
MrEtArn

Reputation: 325

For my use I wrapped yunnosch's answer within a bash script:

#!/bin/bash
# substitute a word in a predefined location disregarding its value
# applied with 4 arguments: ( number of word inside a line, number of line, new value and input text)
# add a 5th argument "-i" to do a in place substitution
echo  substituting the \#$1 word in the \#$2 line with $3
declare -i a=$1
let a-=1
sed -E $5 " $2s/(\s*(\S+\s+){$a})\S+(\s+|$)/\1$3\3/;" $4

Upvotes: 0

Yunnosch
Yunnosch

Reputation: 26703

I am interpreting
"in-place substitution" as
"substitute in a place which is given by line number and word number"
and that "match pattern" refers in sample case to "-1.0", which you do not want occurring hard-coded in the implementation.
I hope the requirement "without matching any pattern" only refers to the actual replacing, allowing more generic pattern matching elsewhere.

My proposed implementation to solve this:

bash-3.1$ sed -E "4s/(\s*(\S+\s+){2})\S+(\s+|$)/\1$i\3/;" input.txt

Output for given sample input (without "..."), for $i==5:

coords xyz
O 0.0 0.0 0.0
H 1.0 1.0 0.0
H 1.0 5 0.0

In the implementation
"4" is the line number,
"2" is the word number (start counting at 0).

In the output "5" is the replacement.

Getting the line number right was already solved by you.
I did the word number by requiring in the regex the right number {n} of preceeding "nonwhitespace + whitespace", i.e. \S+\s+.

Upvotes: 1

Related Questions