ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I was needing help finding out away to search for a block of text across multiple files in multiple directories and replace it found with a new block. Most of the solutions i have found so far are for single line replacements
what i will be editing are php pages, and of course the lovly corp world changed the loction of a few required data fields.
the sad part is some of the lines are indented differently
so some are <tab><tab><tab><TAG> some are <tab><TAG> etc......
For each matching filename, the 'searchAndReplaceCommand' will be invoked, and given the name of the matching file. In this case, a suitable search & replace tool is sed.
Code:
find /top/level/directory -name "*.php" -exec sed -i s/what you have/what you want/g {} \;
sed is given the '-i' option to edit 'in-place', along with a regular expression to substitute all instances of the 'what you have' with 'what you want'. You may use regex expressions, rather than simple literal text to express 'what you have' and 'what you want'.
If you use this, definitely create a backup and a test directory tree first, and examine closely the changes that are made.
--- rod.
No. That isn't what is typically described as 'search and replace'; it seems you want to re-order some lines, which I see as a different task. Still, if you can come up with a way of unambiguously describing how you want to re-order your code, a perl script (for example) could be used instead of sed. Can you put in words the edit(s) you need to make?
BTW, when posting source code, it is helpful to post using [C O D E] tags to preserve formatting and prevent unwanted translations to smilies. It is hard to tell where your code starts and your narrative ends.
Okay, for me to put into words the edit you want to make, it looks like you want to find the line that looks like '<!-- stop main content -->', and make it the first line in the file. If this is incorrect, please state in words (important), what the edit(s) needs to look like. You will need to loosely express an algorithm/process which describes the required changes.
--- rod.
the reason i was wanting to look for the entire block is due to that some of the 4000 pages are correct. So i only need to do it on less than half the pages and i am unsure what pages are done incorrectly.
the block below is about 6 -10 lines from the bottom i want it to retain its location in the file itself .....
Code:
<!-- stop main content -->
<p class="terms"><a href="http:\\url.here.for\link">test</a></p>
</div>
<!-- stop content head -->
to a position preceding the 'stop main content' line.
(This is definitely more complex than search & replace). In perl, the splice function is going to be useful, though. Awk also has the nice feature of being able to identify start-end patterns. Hmmm.
So, you mentioned the possibility of inconsistent use of tabs. It is fairly easy to deal with arbitrary amounts of whitespace in perl regexs's, so this should not be a big problem. Any other inconsistencies? Is the URL in each href attribute constant? What about upper/lower case? Your samples show all lower case. Is there always one and only one of each of the identifiable patterns? Now is the time to think about possible inconsistencies and other unexpected cases.
--- rod.
Okay, try this instead of 'searchAndReplaceCommand' in my original reply.
Code:
#! /usr/bin/perl -w
#
# LQzouriel.pl - Move identified regions of the input file to another identified location
#
# Usage LQzouriel.pl filespec
#
#
#
use strict;
my $startPattern = "<p\\s+class=\\\"terms\\\"><a\\s+href=\\\"http:\\\\\\\\url.here.for\\\\link\\\"\\s*>test</a>\\s*</p>";
my $endPattern = "\\s*</div>\\s*";
my $destinationPattern = "<!--\\s+stop\\s+main\\s+content\\s+-->";
my $startLine = undef;
my $endLine = undef;
my $destLine = undef;
open( INFILE, $ARGV[0] ) || die "Cannot open ",$ARGV[0]," for input : $! \n";
my @file = <INFILE>;
close( INFILE );
for( my $i = 0; $i < @file; $i++ ){
# Make sure we find patterns in the expected order...
if( $file[$i] =~ m/$destinationPattern/ && ! defined( $startLine ) ){
$destLine = $i;
}
elsif( $file[$i] =~ m/$startPattern/ && defined( $destLine ) ){
if( ! defined( $startLine ) ){
$startLine = $i;
}
}
elsif( $file[$i] =~ m/$endPattern/ && defined( $startLine ) ){
$endLine = $i;
}
}
if( defined( $startLine ) && defined( $endLine ) && defined( $destLine ) ){
# print "Start : $startLine\n";
# print "Stop : $endLine\n";
# print "Dest : $destLine\n";
my $segmentLen = 1 + $endLine - $startLine;
#
# Chop out the chunk delimited from startLine to endLine
#
my @fileSegment = splice @file, $startLine, $segmentLen;
#
# Splice in at the destination location
#
splice @file, $destLine, 0, @fileSegment;
}
# For testing, uncomment these three lines and comment out actual file output segment
# print "============\n";
# print @file;
# print "============\n";
open( OUTFILE, ">$ARGV[0]" ) || die "Cannot open $ARGV[0] for writing : $!\n";
print OUTFILE @file;
close( OUTFILE );
You will have to edit the URL to match your real one (those backslashes in the URL are nasty). Clip this into a file, make it executable, and try it on one or two files, manually first. Then, as I said before, create a backup tree and a test tree, run it there and check for expected behavior. I have tested this in only a rudimentary manner, and it did what I expected it to do.
--- rod.
Last edited by theNbomr; 12-07-2007 at 02:25 PM.
Reason: Code fix re: File handles
Uncomment the lines that print the Start-End-Dest linenumbers. If any of those are undefined, it will not modify anything. I tested it by creating a file that was cut & pasted from your first code box in article #5 of this thread.
--- rod.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.