LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Server (https://www.linuxquestions.org/questions/linux-server-73/)
-   -   Find text and replace another field (https://www.linuxquestions.org/questions/linux-server-73/find-text-and-replace-another-field-572415/)

jaysin_aus 07-26-2007 08:45 AM

Find text and replace another field
 
Hi all,

I am wanting to be able to search and replace through linux files.
Now I know how to do the simple search and replace, I want to be able to search, then move along that line a bit and replace another part.

Here's an example that will help:

File text.tmp:
jase1, 'log1' 2000
jase2, 'log2' 3000
jase3, 'log3' 4000

I want to be able to search for jase1, then replace log1 with test1.

After that I want to search again for jase1 and replace 2000 with 5000.

Is this possible and if so, how do you do it?

Any help is greatly appreciated.

best regards,

Jase

kstan 07-26-2007 09:20 AM

make a scrip as below:

Quote:

#/bin/bash

cat yourfilename | grep jase1 | sed 's/log/test/' > 1stresult
cat 1stresult | grep jase1 | sed 's/2000/5000/' > finalstresult


jaysin_aus 07-26-2007 09:39 AM

I am after a script where I can find jase1 and replace whatever is between the ' '
Then to replace whatever is after the second '

TylerD75 07-26-2007 10:12 AM

Edit1: Sorry... didn't answer your question...
Edit2: Came up with a bash script that will solve your problem (hopefully):
Code:

#!/bin/bash
tmpLINE[2]=""                                # Create a global array
OLDtmp="text.tmp"                            # Input file
NEWtmp="new-text.tmp"                        # Output file
tmpP=0                                      # A temp pointer
echo "" > ${NEWtmp}                          # Create/empty the output file
for i in $(cat ${OLDtmp})
do
  tmpLINE[$tmpP]="${i}"
  if [ "${tmpP}" -eq 2 ]
  then
    if [ "${tmpLINE[0]}" == "jase1," ]
    then
      tmpLINE[1]="'test1'"
      tmpLINE[2]="5000"
      echo ${tmpLINE[@]} >> ${NEWtmp}
    else
      echo ${tmpLINE[@]} >> ${NEWtmp}
    fi
    tmpP=0
  else
    let "tmpP += 1"
  fi
done

The above can probably be solved with a shorter script, but I'm not sure how I can read a whole line into one variable ;)

TylerD75 07-26-2007 11:25 AM

Here's one that is a bit more advanced ;) :
Code:

#!/bin/bash
tmpLINE[3]=""
OLDtmp="text.tmp"
NEWtmp="new-text.tmp"
tmpP=0
echo "" > ${NEWtmp}

function replace_words
{
  for i in $(cat ${OLDtmp})
  do
    tmpLINE[$tmpP]="${i}"
    if [ "${tmpP}" -eq 2 ]
    then
      if [ "${tmpLINE[0]}" == "${1}," ]
      then
        tmpLINE[1]="'${2}'"
        tmpLINE[2]="${3}"
        echo ${tmpLINE[@]} >> ${NEWtmp}
      else
        echo ${tmpLINE[@]} >> ${NEWtmp}
      fi
      tmpP=0
    else
      let "tmpP += 1"
    fi
  done
}

function no_args
{
  echo "Error: No arguments..."
  echo "Usage: ${1} <search word> <replace-log-with> <replace-number-with>"
  echo "  Where <search-word> is the word you're searching for, like jase1."
  echo "  <replace-log-with> is the word you want to replace whatever is between the ' and '."
  echo "  And <replace-number-with> is the number you want after the last '."
  echo
  echo "This is not really a helpful response, but you know what I mean ;)"
}
if [ -z "${1}" ] | [ -z "${2}" ] | [ -z "${3}" ]
then
  no_args ${0}
else
  replace_words ${1} ${2} ${3}
fi

The above script will take 3 arguments ex. "./search-and-replace.sh jase1 test1 5000" and output to a new file called "new-text.tmp".
If you need others to use the script I suggest you replace the "no_args" function though...

jaysin_aus 07-26-2007 12:05 PM

Thanks alot for that, will give them a try tomorrow and let you know if I have any problems.

pwc101 07-26-2007 12:23 PM

Unless I am mistaken, this should work:
Code:

sed '/jase1/s/log1/test1/;/jase1/s/2000/5000/g' text.tmp > new_text.tmp
To explain: /jase1/ is a search string.
The 's' is:
Quote:

Originally Posted by man sed
s/regexp/replacement/
Attempt to match regexp against the pattern space. If success-
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.

The part after the ; is the second search (again, for jase1), only this time replacing 2000 with 5000.

Hope that's what you were after!

TylerD75 07-26-2007 01:03 PM

Quote:

Originally Posted by pwc101
Unless I am mistaken, this should work:
Code:

sed '/jase1/s/log1/test1/;/jase1/s/2000/5000/g' text.tmp > new_text.tmp
To explain: /jase1/ is a search string.
The 's' is:The part after the ; is the second search (again, for jase1), only this time replacing 2000 with 5000.

Hope that's what you were after!

Lol, I didn't know you could nest sed searches like that!
Nice one! Definitly going in my "Excellent_Linux_Commands.txt"!

I've made my own iptables generator, where my main problem was how to change .conf variables with the least hassle...
You just simplified everything A LOT! Thanks m8!

But the problem remains... What if you don't know the value of X (i.e. "jase1, 'X' XXXX")?
Then you need to search for everything between '.*' and ' .*$...
How can you search (with sed) for ' ?

pwc101 07-26-2007 01:15 PM

You could also just pipe one sed command into another:
Code:

sed '/jase1/s/log1/test1/g' < text.tmp | \
sed '/jase1/s/2000/5000/g' > new_text.tmp

For more sed classics, see: http://www.student.northpark.edu/pem...d/sed1line.txt

TylerD75 07-26-2007 02:16 PM

Excellent link!

And according to the text there, you can search for hex-ascii codes:
sed '/jase1/s/\x27.*\x27/\x27<newlog-entry>\x27/g' <-- "\x27"="'", so now you can search and replace anything between ' and ' ('s/\x27.*\x27/\x27REPLACED\x27/g')

Now there's no reason to use my LARGE script for something that can be done like this:
Code:

localhost # sed -i '/jase1/s/\x27.*\x27/\x27test1\x27/;/jase1/s/\x27 .*/\x27 5000/g' text.tmp
Which basically searches for all lines containing "jase1", replaces "'*'" with "'test1'" and everything after the last ' with 5000!
Cool!


All times are GMT -5. The time now is 12:14 AM.