Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a single file with a statement that looks like this :

myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(255)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(255)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(255)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(255)
etc

I would like to change this to :

myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(1)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(1)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(1)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(1)
etc

Anyway, the further qualification to the problem is that I only want to change the entries where the name of the attribute ends in 'in$' where $ is a number (like myName_in_3 VARCHAR(255), as an example).

As it happens, the '_in' (Indicator attributes) come in pairs, so doing the n~2 (or FNR%2==0) is quite smart, but I do wonder if it's better to identify the '_in$ VARCHAR(255)' as the pattern for change.

How would I do this using easily understandable code ? The file is not big, so performance is not the main issue .... just trying to avoid a lot of manual vi editing.

share|improve this question
3  
Could you clarify what you need to change? It looks like you want every second 255 to become a 1. Is that correct? Will the values always be 255? –  terdon Aug 21 at 16:46

4 Answers 4

With GNU sed you can specify line addresses in first~step format so to modify every other line starting with the second you could use address 2~2 e.g.

$ sed '2~2 s/(255)/(1)/' file
myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(1)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(1)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(1)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(1)
share|improve this answer
    
Nice! Learn something new about sed everyday. –  HalosGhost Aug 21 at 16:37
1  
@HalosGhost I can't say I've ever used it IRL! –  steeldriver Aug 21 at 16:38

With awk:

$ awk 'FNR%2==0{sub(255,1)}1' file
myName_tx_1 VARCHAR(255)
myName_in_1 VARCHAR(1)
myName_tx_2 VARCHAR(255)
myName_in_2 VARCHAR(1)
myName_tx_3 VARCHAR(255)
myName_in_3 VARCHAR(1)
myAddress_tx_1 VARCHAR(255)
myAddress_in_2 VARCHAR(1)

Explanation

  • FNR%2==0 only matches even lines.
  • If line is even, we replace 255 with 1, sub(255,1).
  • 1 is a true condition, make awk print $0.

The same logic can be used with other tools, like perl:

perl -pe 's/255/1/ unless $. % 2' file

With sed, you can do:

sed -e 'n;s/255/1/' file

Update

With your update requirement, we can change solution a little.

With awk:

awk '/_in_[0-9]/{sub(255,1)}1' file

With sed:

sed -e '/_in_[0-9]/{s/255/1/}' file

With perl:

perl -pe 's/255/1/ if /_in_[0-9]/' file
share|improve this answer
    
+1 for awk. That is the perfect tool for this task. –  HalosGhost Aug 21 at 16:36
    
sure was the same. my bad. and @HalosGhost - obviously the perfect tool was sed - iterative edits are what it was born to do - it is the stream editor. you don't need the -e though.. but - why answer a question you don't find worthwhile? and if you do - why not upvote it? –  mikeserv Aug 21 at 18:47
    
@mikeserv, I'm confused; I didn't answer this question… –  HalosGhost Aug 21 at 18:50
1  
@HalosGhost - oh, I know. Sorry about that. I only meant to (in a playfully competitive sense) address you regarding sed v awk. The rest was for Gnouc because I stupidly repeated his sed answer in a since deleted one of my own. –  mikeserv Aug 21 at 18:57
    
@mikeserv, ahh, fair enough. As much as I love sed, this task seems like it's what awk was designed for. –  HalosGhost Aug 21 at 19:01

There's

sed '/_in_/ s/255/1/'

which means: for lines matching /_in_/, search for 255 and replace with 1.

share|improve this answer
cat oldfile.txt |awk '/_in_[0-9]/{sub(255,1)}1' > newfile.txt
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.