Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Find Pattern and then sub either next line or 2nd line 2

Status
Not open for further replies.

frangac

Technical User
Feb 8, 2004
163
ZA
Hi All,PHV

I have a file that looks like this
<AT 1.1 LV 1.1 NT 3.4.0.0 >O
b
J
2 Q
3 CDR b
J
101 C
S7 A
1 O D
1 D
0 D
0 D
0 D
0 D
0 D
0 D
0 D
128 A <------------- Pattern
9 514058912 A <-- must sub to "10 0514058912"
9 51405EEEE D <-- must sub to "10 051405EEEE"
0 D
0 D
0 A
0 M
1078569424 0 D
2004 D
3 D
6 D
12 D
37 D
4 D
0 D
7 A
Ap

PHV Thanks for your assistance
First find pattern (128 A)and then read next line (9 514058912), sub the next line to (12 123456789) or alternatively read the 2nd line(9 51405EEEE) , sub the 2nd line to (15 CHRIS).
 
What are the EXACT criterias ?

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
Hi PHV,

Here goes, case option in first_line

1)Firstly, find pattern (128 A ) and then read next line (9 514058912), prompt user : a) 9 514058912, please enter change -> read change1 change2, and then sub $change1 and $change2 with 9 aand 514058912 end.

case option in second_line after pattern

2)Secondly, find pattern (128 A ) and then read the 2nd line after pattern search. Prompt user b)9 51405EEEE, please enter change -> read change1 change2 , and then sub $change1 and $change2 with 9 51405EEEE

Hope this makes sense,
Thanks once again

Chris
 
Something like this (typed and untested)?
awk -v opt=1or2 'BEGIN{tty="/dev/tty"}
/^128 A/{a=NR}
a&&NR==(a+opt){
printf "%c) %s %s, please enter change",96+opt,$1,$2>tty
if((getline reply<tty)>0)
if(split(reply,arr)==2){$1=arr[1];$2=arr[2]}
}1' /path/to/input >output

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
[tt]
BEGIN { stderr = "/dev/stderr" }

/^128 A/ {found=-2; print; next}
found { print "#"found+3" line after '128 A':">stderr
print $0 >stderr
printf "Change to: " >stderr
getline s <"-"
print s
found++
next
}
1
[/tt]
Save in file "change.awk" and run with "awk -f change.awk dataFile >outputFile".
 
Hi PHV (MIS),

Thanks for your posting.
Almost there, but is the a way that we can show only the output ( result from line ) and then prompt for change, take that change and then sub into the file, with a print option to show the change.

Clear enough!

Many Thanks
Chris
 
Sorry, don't understand your last post. Don't blame me as I'm a french guy with limited non technical english knowledge.
Anyway, thanks for the star.
 
PHV,

What I am trying to say is that, print the line out that is found after pattern opt=1or2 e.g.

Line 1
======
9 514058912 : Please enter New Number-->\c
read number

and then sub the $number in place of 9 514058912 , print the whole file, to show the changes.

Merci

futurelet,

Thanks for your post, but it complains about the path
"awk: Cannot find or open file /dev/stderr". Need help

Thanks
Chris
 
Something like this ?
awk -v opt=1or2 'BEGIN{tty="/dev/tty"}
/^128 A/{a=NR}
a&&NR==(a+opt){
printf "Line %d\n======\n%s %s : Please enter New Number-->",opt,$1,$2
if((getline reply<tty)>0){$1=reply;$2=""}
}
{buf[NR]=$0}
END{for(i=1;i<=NR;++i)print buf}' /path/to/input

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
[tt]
BEGIN { tty = "/dev/tty" }

/^128 A/ {found=-2; print; next}
found { print "#"found+3" line after '128 A':">tty
print $0 >tty
printf "Change whole line to: " >tty
getline s <"-"
changes = changes $0 " >> " s "\n"
$0 = s
found++
}
1
END { print "Changes:" >tty
print changes >tty
}
[/tt]
 
When it asks you for a change, if you hit <ENTER> without typing anything else, no change will be made.
[tt]
BEGIN { tty = "/dev/tty" }

/^128 A/ {found=-2; print; next}
found { print "#"found+3" line after '128 A':">tty
print $0 >tty
printf "Change whole line to: " >tty
getline s <"-"
# If you didn't type anything but <ENTER>,
# no change will be made.
if ( s )
{ changes = changes $0 " >> " s "\n"
$0 = s
}
found++
}
1
END { print "Changes:" >tty
print changes >tty
}
[/tt]
 
PHV,Futurelet,

They are both brilliant.
Please be so kind to post me an explanation for each line, if possible for e.g {buf[NR]=$0} ? and {found=-2 why ?

Many Thanks to both
Chris
 
awk -v opt=1or2 '
Launch awk with variable opt initialized to the desired line offset from the searched pattern
BEGIN{tty="/dev/tty"}
Assign "/dev/tty" to variable tty for further interaction with user without breaking the stdin/stdout mechanism
/^128 A/{a=NR}
When desired pattern is found, note its line number
a&&NR==(a+opt)
If the pattern was found and we're on the desired line
{printf "Line %d\n======\n%s %s : Please enter New Number-->",opt,$1,$2>tty
Ask the user for new data after showing him the line offset and the values of the first two fields
if((getline reply<tty)>0){$1=reply;$2=""}}
If the user don't hit the EOF key (usually ^D) then replace the first two fields with their input
{buf[NR]=$0}
Load the input file (with amended line) in an array named buf indexed by line number
END{for(i=1;i<=NR;++i)print buf[ignore][/ignore]}' /path/to/input
At the end of the input file, dump the buf array to show the user the changes made

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
I set found = -2 because I want to work on the next 2 lines
read from the file. When each of the next 2 lines is processed, found is increased by 1; when it becomes 0, no
more lines will be processed until "128 A" is found again.
There are other ways to do it; I could have used found=2 and
counted down to 0, but doing it this way seemed to make it easier to have the next two lines numbered in ascending sequence ("#1", "#2") when printing them to the screen so that the user can change them. When you write your own code, do it the way that is most understandable for you.
 
If you awk version doesn't support /dev/stderr, you can do :

[tt]
BEGIN { stderr = "cat 1>&2" }
/^128 A/ {found=-2; print; next}
found { print "#"found+3" line after '128 A':" | stderr
print $0 | stderr
[/tt]

Jean Pierre.
 
PHV and Futurelet,

Many Thanks for the write up.

PHV,

In your script, how can I print the results after sub, without showing the user changes, just like Futurelet, redirect the output to another file.

By the way is there only one star giving per answer or can you allocate more than one star, and where can this be done.


Thanks
Chris
 
frangac
and then sub the $number in place of 9 514058912 , print the whole file, to show the changes.

In your script, how can I print the results after sub, without showing the user changes, just like Futurelet, redirect the output to another file.


The rules seems to be randomly assigned :)

Something like this ? (extra bonus: a log of changes)
awk -v opt=1or2 'BEGIN{tty="/dev/tty"}
/^128 A/{a=NR}
a&&NR==(a+opt){
printf "Line %d\n======\n%s %s : Please enter New Number-->",opt,$1,$2
if((getline reply<tty)>0){
printf "%d Before: %s\n",NR,$0 >"change.log"
$1=reply;$2=""
printf "%d After: %s\n",NR,$0 >"change.log"
}

}
{buf[NR]=$0}
END{for(i=1;i<=NR;++i)print buf}
' /path/to/input >output

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
PHV,

Thanks for the responce,

In your
{buf[NR]=$0}
END{for(i=1;i<=NR;++i)print buf}
' /path/to/input >output

Where you put "> output", it does not show the "

Line 1
======
10 0313621139 : Please enter New Number-->"

but if you look at the output file, you can see the "Please enter New Number-->".

If you dont specify the output file then it works fine.

What am I doing wrong?

Chris
 
I apologize for the lack of stdout tracking:
awk -v opt=1or2 'BEGIN{tty="/dev/tty"}
/^128 A/{a=NR}
a&&NR==(a+opt){
printf "Line %d\n======\n%s %s : Please enter New Number-->",opt,$1,$2 [red]>tty[/red]
if((getline reply<tty)>0){
printf "%d Before: %s\n",NR,$0 >"change.log"
$1=reply;$2=""
printf "%d After: %s\n",NR,$0 >"change.log"
}
}
{buf[NR]=$0}
END{for(i=1;i<=NR;++i)print buf}
' /path/to/input >output

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top