LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   find a word in a file, and change a word beneath it ?? (https://www.linuxquestions.org/questions/programming-9/find-a-word-in-a-file-and-change-a-word-beneath-it-620827/)

vikas027 02-13-2008 08:53 AM

find a word in a file, and change a word beneath it ??
 
Hi all,

I have a file with lines written somewhat like this.

Code:

aaaa
ccc
aa
linux
browse = no
xssxw
cdcedc
dcsdcd
csdw
police
dwed
dwd
browse = no


cdecec
dsdc
cdc
wd

wdcew
dwed
market
browse = yes

dwdw
wedwe
we

I would like to search word police (which is in middle of file)
and then change the line from browse = no to browse = yes which is after two lines from the word police.

Pls help... I am not so advanced in scripting.

Thanks in advance,
Vikas

radoulov 02-13-2008 09:09 AM

Code:

sed '/police/{n;n;n;s/no/yes/;}' filename

vikas027 02-13-2008 02:23 PM

Quote:

Originally Posted by radoulov (Post 3055718)
Code:

sed '/police/{n;n;n;s/no/yes/;}' filename


thanks a lot,
will try this code & revert.

firstfire 02-14-2008 01:59 AM

Hello.

You can try following ed script:
Code:

/police/
/browse/
s/no/yes
wq

Save it to file or generate using bash script and run:
Code:

ed filename < script

osor 02-14-2008 12:55 PM

The OP wasn’t clear whether the line “browse = no” is always three lines after the original word. If not (i.e., if the number of lines is variable), radoulov’s script might not work.

You can, use sed, though (if you want):
Code:

sed '/police/{:n;n;s/no/yes/;t;bn}' filename

pixellany 02-14-2008 01:41 PM

Quote:

Originally Posted by osor (Post 3057117)
The OP wasn’t clear whether the line “browse = no” is always three lines after the original word. If not (i.e., if the number of lines is variable), radoulov’s script might not work.

You can, use sed, though (if you want):
Code:

sed '/police/{:n;n;s/no/yes/;t;bn}' filename

If I am not mistaken, this is a loop in sed. (Don't see that too often...)

Does the "t" with no label take you out of the loop?
The way I read this, once it finds "police", it loops until in finds the first instance of "no". It then continues parsing looking for the next instance of "police". Any instance of "police" before a "no" will get ignored.

osor 02-14-2008 04:50 PM

Quote:

Originally Posted by pixellany (Post 3057151)
Does the "t" with no label take you out of the loop?

Yes, t ends the cycle (or equivalently, jumps to the end) if the substitution succeeded. The reason for the “t;bn” construct is the lack of a “jne” operation in sed (if you are familiar with assembly). So you construct an artificial jne by using a je (i.e., t) followed by a jmp (i.e., b), where the target of the je is the instruction after your jmp (in this case, the target happens to be the end, so you don’t need an explicit label).
Quote:

Originally Posted by pixellany (Post 3057151)
Any instance of "police" before a "no" will get ignored.

I think you mean any instance of “no” before a “police” will get ignored.

pixellany 02-14-2008 07:51 PM

Quote:

Originally Posted by osor (Post 3057305)
I think you mean any instance of “no” before a “police” will get ignored.

No--I meant it the way I wrote it. I am assuming that, after finding "police", it then loops looking for a "no". If there is another "police" before finding "no", then I am guessing that it will not look for "no" after (because it is stuck in the loop looking for "no".

jschiwal 02-14-2008 07:57 PM

From the structure of the example, it looks like the "browse=no" ends the paragraph.

sed '/police/,/^$/s/browse = no/browse = yes/' data

I'll do something similar to select a device from an lspci -v list:
Code:

sudo /sbin/lspci -v | sed -n '/FireWire/,/^$/p'
root's password:
03:05.0 FireWire (IEEE 1394): Agere Systems FW323 (rev 61) (prog-if 10 [OHCI])
        Subsystem: Hewlett-Packard Company Unknown device 2a34
        Flags: bus master, medium devsel, latency 32, IRQ 19
        Memory at fddff000 (32-bit, non-prefetchable) [size=4K]
        Capabilities: [44] Power Management version 2

Breaking up sections of output with blank lines make it easy to process with sed or awk.

sundialsvcs 02-14-2008 08:20 PM

Another useful tool to consider for such applications is awk.

This is a tool that "takes sed to the next level." Like most power-tools, the concept behind this tool is disarmingly simple:
  1. The "program" consists of one or more regular-expressions ("text patterns"...) followed by blocks of executable code, expressed in a somewhat C-like language. There are also two special patterns, BEGIN (executed before the first line) and END (executed after the last one).
  2. awk takes each "line" (as defined by you...) and considers each regular-expression in turn. When it finds one, it executes the corresponding code-block.
  3. It can be "that simple" or, if your needs require, much more elaborate.
What this gives you, then, is a very powerful and generalized solution for problems like the one you are dealing with. awk is great for "grabbing all kinds of things out of text-files and manipulating them in some useful way."

The perl programming-language sort of "started where awk ended, and then kept on going well into the next galaxy." But that's another story.

The bottom line is that Unix/Linux environments have "an embarrassment of riches" in terms of very practical programming tools. It's well worth getting to know them.

ghostdog74 02-14-2008 09:46 PM

@OP, if you have Python
Code:

!#/usr/bin/python
data=open("file").readlines()
for n,items in enumerate(data):
    if "police" in items:
        data[n+3] = data[n+3].replace("no","yes")
print ''.join(data)

if you prefer awk, one way
Code:

awk '/police/{line=NR+3;}
NR == line { sub("no","yes"); }1
' file



All times are GMT -5. The time now is 08:31 AM.