LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-02-2011, 03:00 PM   #1
rock1961
LQ Newbie
 
Registered: Mar 2010
Posts: 6

Rep: Reputation: 0
awk and sed questions


i have a mrtg config file that i am trying to replace some strings in. the format of the lines in question are like this

Title[3560-1_10127]: Traffic Analysis for 10127 -- 3560-1

where the 2nd instance on the line of 10127 needs replaced with the string "Port 27". thats easy to do with sed but what i want to do is to do that for all the ports incrementing my way through the file. in other words, there are lines that say 10101 through 10148 and i want to replace the 2nd instance on the line of 10101 with "Port 1" and then go onto the line with 10102 and replace its 2nd instance with "Port 2"

this is breaking my brain. any of you have any ideas?

thanks
 
Old 08-02-2011, 03:10 PM   #2
crts
Senior Member
 
Registered: Jan 2010
Posts: 2,020

Rep: Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757
Hi,

do you mean something like this?
Code:
sed -nr 's/(Title\[.*_([0-9]{3}([0-9]{2})).*)\2/\1Port \3/p' file
If this is not what you are looking for then you will have to provide a more representative example and what results you expect.
 
Old 08-02-2011, 04:42 PM   #3
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Here's a gawk program that works for your sample:
Code:
$ cat rock1961.gawk
#!/bin/gawk -f
/\[[[:digit:]-]+_[[:digit:]]+\]/ {
  input=$0
  n=split(input,part,/[[\[\]_]/)
  if (input ~ " " part[3]) {
    port=substr(part[3],4)+0
    sub(" " part[3], " Port " port, input)
  }
  $0=input
}
{print}
and here's the output:
Code:
$ cat rock1961.txt
Title[3560-1_10127]: Traffic Analysis for 10127 -- 3560-1

$ ./rock1961.gawk rock1961.txt 
Title[3560-1_10127]: Traffic Analysis for Port 27 -- 3560-1
Notes:
  1. This assumes that your port number is derived from the second part of the code in the square brackets by removing the first three digits of that part.
  2. To make the script executable, you need to do a chmod +x with the script name as the second argument.
  3. The input is copied to /dev/stdout, with the targeted lines altered. To write it to a file, just redirect the output to whatever file you wish. (E.g., ./rock1961.awk data.file > altered_data.file)
  4. The target lines are selected by the presence of the [nnn-nn_nnnnn], but not checked for the "Title" at the start. If that would be useful, just change the selection criteria from /\[[[:digit:]-]+_[[:digit:]]+\]/ to /Title[[:space:]]*\[[[:digit:]-]+_[[:digit:]]+\]/

Last edited by PTrenholme; 08-02-2011 at 05:11 PM.
 
1 members found this post helpful.
Old 08-02-2011, 05:11 PM   #4
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
In GNU awk the gensub function can replace the Nth occurrence of a matching pattern:
Code:
awk '{$0=gensub(/101([0-9][0-9])/,"Port \\1",2)}1' file
Anyway this leaves leading zeros in front of Port numbers from 1 to 9. A bit more tricky if you want to remove them:
Code:
awk '{port=gensub(/.*101([0-9][0-9]).*/,"\\1","g");print gensub(/101([0-9][0-9])/,("Port " port+0),2)}'

Last edited by colucix; 08-02-2011 at 05:16 PM.
 
Old 08-02-2011, 05:14 PM   #5
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
You might want to consider always using at least the maximum number of digits required for the largest port number, with leading zeros. This makes the listing sort well, since the alphabetic form and the numeric form sort the same. Might not apply to your situation, but if it does, now is the time to get it right.

--- rod.

Edit: wouldn't you know someone would say the same thing while I was typing. Note to self: learn to type fasterer.

Last edited by theNbomr; 08-02-2011 at 05:15 PM.
 
Old 08-02-2011, 06:09 PM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
sed can also replace the nth instance on a line.
Code:
sed -i -r 's/101([0-4][0-9])/Port \1/2' file
This is a little off though, since it will match everything from 10100-10149. It sure would be nice if regex could match number sequences larger than one digit.

So you'd probably have to embed it in a shell loop instead to match each number in turn, and fool with zero-padding as well.

bash v.4's zero-padding in brace-expansion makes it relatively easy.
Code:
for num in {01..48}; do

     sed -i "s/101${num}/Port ${num#0}/2" file

done
Change the brace expansion to "{0{1..9},{10..48}}" for v.3.
 
Old 08-02-2011, 06:14 PM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,999

Rep: Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190Reputation: 3190
Also if you know the format is always the same:
Code:
awk '$5 = "Port " int(substr($5,4))' file
 
Old 08-03-2011, 09:06 AM   #8
rock1961
LQ Newbie
 
Registered: Mar 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Solved Awk question

Quote:
Originally Posted by PTrenholme View Post
Here's a gawk program that works for your sample:
Code:
$ cat rock1961.gawk
#!/bin/gawk -f
/\[[[:digit:]-]+_[[:digit:]]+\]/ {
  input=$0
  n=split(input,part,/[[\[\]_]/)
  if (input ~ " " part[3]) {
    port=substr(part[3],4)+0
    sub(" " part[3], " Port " port, input)
  }
  $0=input
}
{print}
and here's the output:
Code:
$ cat rock1961.txt
Title[3560-1_10127]: Traffic Analysis for 10127 -- 3560-1

$ ./rock1961.gawk rock1961.txt 
Title[3560-1_10127]: Traffic Analysis for Port 27 -- 3560-1
Notes:
  1. This assumes that your port number is derived from the second part of the code in the square brackets by removing the first three digits of that part.
  2. To make the script executable, you need to do a chmod +x with the script name as the second argument.
  3. The input is copied to /dev/stdout, with the targeted lines altered. To write it to a file, just redirect the output to whatever file you wish. (E.g., ./rock1961.awk data.file > altered_data.file)
  4. The target lines are selected by the presence of the [nnn-nn_nnnnn], but not checked for the "Title" at the start. If that would be useful, just change the selection criteria from /\[[[:digit:]-]+_[[:digit:]]+\]/ to /Title[[:space:]]*\[[[:digit:]-]+_[[:digit:]]+\]/
this was the ticket. running this script against the file first and redirecting to another file and then changing the Title string to PageTop and running it again against the new file did exactly what i wanted. that you so much for your help.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
awk/sed help mailvaganam Programming 5 05-03-2011 12:35 AM
awk or sed to for this questions solution ? cs24 Programming 7 03-20-2010 05:23 AM
sed or awk ilo Programming 1 08-22-2008 10:38 AM
SED/AWK help bioinformatics_guy Linux - Newbie 1 08-12-2008 05:07 AM
Sed and Awk Gins Programming 7 04-19-2006 10:32 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:39 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration