LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
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 03-07-2017, 08:52 AM   #1
vincix
Senior Member
 
Registered: Feb 2011
Distribution: Ubuntu, Centos
Posts: 1,240

Rep: Reputation: 103Reputation: 103
match newline, space, newline


Given the following text:
Code:
Consult Section 3.1 in the Owner and Operator

 Guide for a description of the tape drives
available on your system.
I'm trying to substitute "Owner and Operator" with "Installation" and to bring "Guide" on the same line, so as to read "Installation Guide", and then start a newline (the last thing is easy). But to do that I want to match "Owner and Operator*newline*newline*space*. Even more, I would like it to match any combination of newline and spaces (perhaps including tabs), regardless of the order. For example, newline-space-newline or doublespace-newline-tab-newline and so on, and so forth.

If I remember correctly, you could do it with square brackets, but I'm not sure how I can do that using \n, \s or \t or regex classes.

This is the original idea:
Code:
/Owner/{
N
s/Owner *\n*and *\n*Operator *\n*Guide/Installation Guide\
/
}
which matches "Owner Operator Guide", even if it's broken across multiple lines, but it doesn't take into account tabs or spaces that occur after the newline,or tabs before the line or some other random order.
 
Old 03-07-2017, 12:30 PM   #2
vincix
Senior Member
 
Registered: Feb 2011
Distribution: Ubuntu, Centos
Posts: 1,240

Original Poster
Rep: Reputation: 103Reputation: 103
I guess one of the first problems I need to solve is to somehow 'catch' the second newline. The first newline is caught with N (if I understand correctly). So how can I match several newlines?
 
Old 03-07-2017, 01:22 PM   #3
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931
Hi vincix,

I've moved this thread to the Programming forum. I know that persons regularly on the Programming forum will have some thoughts. Myself, I've not played much with newline and regex, instead I've always tackled that internally within an editor a'la copy or cut and then paste that into the search-replace buffer.
 
2 members found this post helpful.
Old 03-07-2017, 01:52 PM   #4
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
This is a brute-force solution.

With this InFile ...
Code:
Consult Section 3.1 in the Owner and Operator

 Guide for a description of the tape drives
available on your system.
 
This is another paragraph.
 
This is yet another paragraph.
... this code ...
Code:
tr "\n" "~" <$InFile  \
|sed 's/Owner and Operator~~ Guide /Installation Guide~/g'  \
|tr "~" "\n"  \
>$OutFile
... produced this OutFile ...
Code:
Consult Section 3.1 in the Installation Guide
for a description of the tape drives
available on your system.
 
This is another paragraph.
 
This is yet another paragraph.
Explanation:
tr replaces all newlines with tilde.
sed implements the desired transformation.
tr replaces all tildes with newlines.

Daniel B. Martin
 
2 members found this post helpful.
Old 03-07-2017, 02:11 PM   #5
vincix
Senior Member
 
Registered: Feb 2011
Distribution: Ubuntu, Centos
Posts: 1,240

Original Poster
Rep: Reputation: 103Reputation: 103
I find it a little bit hard to digest it, but at the same time the logic seems simple enough. So you're using tildes just for transition. That's interesting. Thanks. I did expect it to solve it only with sed, just to get to know the tool better, but I guess it's unecessarily intricate.
 
Old 03-07-2017, 02:20 PM   #6
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Quote:
Originally Posted by vincix View Post
I find it a little bit hard to digest it, but at the same time the logic seems simple enough. So you're using tildes just for transition. That's interesting. Thanks. I did expect it to solve it only with sed, just to get to know the tool better, but I guess it's unnecessarily intricate.
The first tr changes the entire file into one long line, with tildes as "ghosts" of former newlines. The sed becomes less complicated because it isn't trying to "peek" one or two lines ahead. After sed does its work, another tr replaces any remaining "ghosts" with newlines.

Daniel B. Martin
 
Old 03-07-2017, 04:58 PM   #7
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206
Here is one that works with sed only:

Code:
$ sed -r '/Owner/,/Guide/{:a;N;$!ba;s/[ \t\n]+/ /g;s/Owner and Operator/Installation/;s/Guide /Guide\n/}' file.txt
Consult Section 3.1 in the Installation Guide
for a description of the tape drives available on your system.
I have put it on a single line, but you might want to break it up for readability.

UPDATE: End address had no effect because of inner loop as pointed out by danielbmartin - but I had not noticed because with simpler infile it did not matter in quick testing. Moving end address to inner loop test (where it should have been) fixes it for longer infiles, see below.

Last edited by astrogeek; 03-07-2017 at 11:44 PM. Reason: Improved /Guide../
 
Old 03-07-2017, 06:12 PM   #8
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Quote:
Originally Posted by astrogeek View Post
Here is one that works with sed only:

Code:
$ sed -r '/Owner/,/Guide/{:a;N;$!ba;s/[ \t\n]+/ /g;s/Owner and Operator/Installation/;s/Guide /Guide\n/}' file.txt
Using the InFile shown in post #4 this sed produced this OutFile ...
Code:
Consult Section 3.1 in the Installation Guide
for a description of the tape drives available on your system. This is another paragraph. This is yet another paragraph.
It blew away the newlines which separate paragraphs.

Daniel B. Martin
 
1 members found this post helpful.
Old 03-07-2017, 06:27 PM   #9
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,269
Blog Entries: 24

Rep: Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206Reputation: 4206
AH! So it did! I was working only with the original file snippet.

Try this then...

Code:
$ sed -r '/Owner/{:a;N;/Guide/!ba;s/[ \t\n]+/ /g;s/Owner and Operator/Installation/;s/Guide */Guide\n/}' file.txt
Consult Section 3.1 in the Installation Guide
for a description of the tape drives
available on your system.

This is another paragraph.

This is yet another paragraph.
I see a few other changes that could be made, but I think this meets the originally stated conditions. The main point being, of course, to remove multi-line whitespace between the start and end condition and make the given replacements, adjust to suite actual requirements!

Last edited by astrogeek; 03-07-2017 at 06:40 PM. Reason: Simpler and added comment... meh typos...
 
1 members found this post helpful.
Old 03-09-2017, 01:29 PM   #10
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,830

Rep: Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216
Code:
/Owner and Operator/{
# substitute what has matched
s//Installation/
:L
# append the following line with a \n
N
# delete it if blank
s/\n *$//
# repeat if successful
tL
# join the following line
s/\n//
}

Last edited by MadeInGermany; 03-09-2017 at 01:30 PM.
 
Old 03-09-2017, 02:10 PM   #11
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,830

Rep: Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216
A multi-line replacement can be done with perl:
Code:
perl -pe 'BEGIN {undef $/} s/Owner\s+and\s+Operator\s+Guide/Installation Guide\n/'

Last edited by MadeInGermany; 03-09-2017 at 02:18 PM. Reason: \n
 
Old 03-09-2017, 02:27 PM   #12
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Mint 17.3
Posts: 1,881

Rep: Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660Reputation: 660
Quote:
Originally Posted by MadeInGermany View Post
A multi-line replacement can be done with perl:
Code:
perl -pe 'BEGIN {undef $/} s/Owner\s+and\s+Operator\s+Guide/Installation Guide\n/'
With this InFile ...
Code:
Consult Section 3.1 in the Owner and Operator

 Guide for a description of the tape drives
available on your system.
 
This is another paragraph.
 
This is yet another paragraph.

Consult Section 3.2 in the Owner and Operator

 Guide for a description of the disk drives
available on your system.
 
This is another paragraph.
 
This is yet another paragraph.
... the perl solution treats only the first Owner and Operator text string. Previous solutions in this thread handle all instances. Is there an easy fix?

Daniel B. Martin
 
Old 03-09-2017, 02:31 PM   #13
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,830

Rep: Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216Reputation: 1216
Sure, with the /g modifier.
The whole file is treated as one line (and must fit into memory).
Code:
perl -pe 'BEGIN {undef $/} s/Owner\s+and\s+Operator\s+Guide/Installation Guide\n/g'
 
1 members found this post helpful.
Old 03-09-2017, 03:14 PM   #14
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
You can do it in vi with:
Code:
:%s/Owner and Operator\n\n Guide /Installation Guide^M/g
Note that to get that "^M" you would hit Ctrl+v Enter
 
  


Reply



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
How to replace the space with newline character after every nth field in a line surajchalukya Linux - Newbie 13 03-08-2013 09:58 PM
replace space with newline and save result in a variable sktimmy Linux - General 5 11-01-2011 11:56 AM
[SOLVED] How to replace newline pattern in file by other newline pattern in a shell script XXLRay Linux - Software 9 11-29-2010 07:57 AM
VI replacement: newline for newline not working! jhwilliams Linux - Software 3 08-16-2007 06:11 PM
What is a newline? raptorsoft2000 Linux - Newbie 6 08-04-2003 10:05 PM

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

All times are GMT -5. The time now is 03:03 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