From owner-freebsd-questions@FreeBSD.ORG Thu Jan 12 13:03:33 2006 Return-Path: X-Original-To: freebsd-questions@freebsd.org Delivered-To: freebsd-questions@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 59B0716A41F for ; Thu, 12 Jan 2006 13:03:33 +0000 (GMT) (envelope-from keramida@ceid.upatras.gr) Received: from rosebud.otenet.gr (rosebud.otenet.gr [195.170.0.94]) by mx1.FreeBSD.org (Postfix) with ESMTP id B254E43D49 for ; Thu, 12 Jan 2006 13:03:31 +0000 (GMT) (envelope-from keramida@ceid.upatras.gr) Received: from flame.pc (aris.bedc.ondsl.gr [62.103.39.226]) by rosebud.otenet.gr (8.13.4/8.13.4/Debian-8) with SMTP id k0CD3SYH017177; Thu, 12 Jan 2006 15:03:28 +0200 Received: by flame.pc (Postfix, from userid 1001) id 1BA6311755; Thu, 12 Jan 2006 15:01:57 +0200 (EET) Date: Thu, 12 Jan 2006 15:01:57 +0200 From: Giorgos Keramidas To: Kristian Vaaf , lars@gmx.at Message-ID: <20060112130157.GB1167@flame.pc> References: <43C56D47.1040809@gmx.at> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <43C56D47.1040809@gmx.at> Cc: freebsd-questions@freebsd.org Subject: Re: My script to replace strings in ASCII files X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Jan 2006 13:03:33 -0000 On 2006-01-11 21:40, lars wrote: >Kristian Vaaf wrote: >> Just curious, what do I need to do to be able to execute this >> script like: >> >> $ text-replace old_string new_string >> >> I find it a bit inconvenient having to edit the script for >> every thing I need to replace. It is. You should start using $1, $2, ... for options. >> #!/usr/local/bin/bash >> # >> # Replace old with new inside all text files. >> # $URBAN: text-replace.sh,v 1.0 2005/10/24 15:09:05 vaaf Exp $ >> # >> >> for file in `find . -type f ! -name ".*"`; do >> >> if [ "`file -b "$file" | grep text`" != "" ]; then >> >> sed -i '' "s/old/new/g" "$file" >> >> echo "$file: Done" >> >> fi >> >> done > > Why not open the file with vim and then > :.,$s/old/new/ Heh, that's nice, and it may even work with multiple files using vim's -c option in a way similar to sed(1): vim -c ':%s/old/new/' file > Of course that's not scriptable... Using the -c option shown above, it may be scriptable too :) > Maybe you should interpolate the first and the second argument > into your regexes in the substitution with sed, > so you get "s/argument1/argument2/" > > Perl might help though. This opens a whole can of worms though. What if the user defined command-line parameters contain special characters (i.e. single quote, double quotes, etc.)? Instead of having to go through all the hoops of parsing quotes and other special characters in a shell script, and then invoking sed on each file, passing one file at a time, I prefer using "in place editing": $ grep emacs .bashrc export EDITOR='nemacs' alias emacs='nemacs' $ perl -pi -e "s/'nemacs'/'emacs'/g" .bashrc $ grep emacs .bashrc export EDITOR='emacs' alias emacs='emacs' $ perl -pi -e "s/'emacs'/'nemacs'/g" .bashrc $ grep emacs .bashrc export EDITOR='nemacs' alias emacs='nemacs' $ The number of files passed as 'extra' arguments to perl in this case is only limited by the amount of text that can fit in a single command-line, and if that's not enough you can use xargs(1) to work around the limit: find . -type f -name \*foo\* | xargs perl -pi -e "s/old/new/g" So, there's no need to write special shell scripts to do this :)