LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 01-26-2004, 01:37 AM   #1
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Rep: Reputation: 15
How to read and change the contents of a text file?


Hi All,
I am using shell script programming and I have text file consistes of 2 fields separated with TAB space, I want to search for a specific value in the second feild then change that value and then read the value of the first field of the same record.

the text file is

0 198.12.45.30
1 250.12.180.129
2 110.115.20.128
3 200.200.2.200

for example I want to find the value 110.115.20.128, change it to 0.0.0.0 and read the value of the first field for the same record which is 2.

so could u tell me how can I do this operation by using shell script programming?

Regards
Bassam
 
Old 01-26-2004, 04:48 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
This should work:
Code:
#!/bin/sh

# grab/check input
OLD_VAL=$1
NEW_VAL=$2
if [[ ${OLD_VAL} == "" || ${NEW_VAL} == "" ]]
then
  echo "No correct input given."
  echo "Exiting now."
  exit 1
fi

# set textfile and tmpfile
INFILE="text.file"
TMPFILE="/tmp/text.file.tmp"

# is value present
HIT=$(grep "${OLD_VAL}" ${INFILE} | cut -f1)

if [[ ${HIT} != "" ]]
then # yep, present
  echo "First field: ${HIT}"
  sed "s/${OLD_VAL}/${NEW_VAL}/" ${INFILE} > ${TMPFILE}
  cp ${TMPFILE} ${INFILE}
else # nope, not present
  echo "Could not find: ${OLD_VAR}"
fi
If any of the code in\s unclear for you, just let me know and I will explain it.
Hope this helps.

Last edited by druuna; 01-26-2004 at 05:07 AM.
 
Old 01-26-2004, 05:16 AM   #3
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
Hi druuna,
Thanks for replying my request, I went through your code theoritically, but I have a point here. Actually my text file may have repeated data (110.115.20.128 can be found in more than one record) and I want to locate and replace only the first accurence in that file, at this time what can I do. I am sorry cause I did not mentioned that previously
 
Old 01-26-2004, 05:39 AM   #4
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
One more thing I want to remention it again, is that how to read the first field when I find the matching in the second feild. That code does not do this operation.
 
Old 01-26-2004, 06:39 AM   #5
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Ok, here's the code with changes for your first comment (only change first occurence):
Code:
#!/bin/sh

# grab/check input
OLD_VAL=$1
NEW_VAL=$2
if [[ ${OLD_VAL} == "" || ${NEW_VAL} == "" ]]
then
  echo "No correct input given."
  echo "Exiting now."
  exit 1
fi

# set textfile and tmpfile
INFILE="text.file"
TMPFILE="/tmp/text.file.tmp"

# on which line is value present (if any)
LI_NO=$(sed -n "/${OLD_VAL}/=" text.file | sed -n '1p' )

# did we find a hit
if [[ ${LI_NO} != "" ]]
then # yep
  OLD_LINE=$(sed -n "${LI_NO}p" ${INFILE})
  sed "${LI_NO}s/${OLD_VAL}/${NEW_VAL}/1" ${INFILE} > ${TMPFILE}
  cp ${TMPFILE} ${INFILE}
  NEW_LINE=$(sed -n "${LI_NO}p" ${INFILE} )
else # nope
  echo "Could not find: ${OLD_VAR}"
fi

echo "This has changed:"
echo "Old line: ${OLD_LINE}"
echo "New line: ${NEW_LINE}"
I'm not sure if I understood the second question/remark (remention it again). I hope that the new addition at the end is what you wanted. Just let me know if it's still not ok.

Last edited by druuna; 01-26-2004 at 06:40 AM.
 
Old 01-26-2004, 08:21 AM   #6
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
Dear druuna,
I am really thankful for your help, the second code is work perfectly. Kindly, can you refer me to a tutorial reference with examples about the sed command and how to be used? because I am sure I will need to use it in the future.

Second thing, I am going to issue a new post about how to change the values of a function parameters from within the function itself and return back to the main shell program
 
Old 01-26-2004, 08:22 AM   #7
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
so I need your help about the second issue
 
Old 01-26-2004, 08:45 AM   #8
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
A few SED related links:

http://www.grymoire.com/Unix/Sed.html
http://sed.sourceforge.net/grabbag/tutorials/

Also take a look at the following book:

http://www.oreilly.com/catalog/sed2/

I will take a look at your other question (could be a while, I'm working atm )
 
Old 02-08-2004, 10:05 PM   #9
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
Hello Druuna,
This is me again "Bassam", I am facing a simple problem with the code up that u helped me with. The problem is that when we change the $OLD_VAL with the $NEW_VAL and save the result in an $TMPFILE, the first resultant line in the $TMPFILE is not arranged as the rest lins in the file. This makes for me a big problem when I come later to search for the value of the first line which I can not find it.

For example
OLD_VAL=0.0.0.0
NWE_VAL=192.168.2.5
and the original contents of the $INFILE is
1 0 0.0.0.0
1 1 0.0.0.0
1 2 0.0.0.0
1 3 0.0.0.0
. . .
. . .
. . .
1 254 0.0.0.0

after we lunch the prgram, the result of the $TMPFILE is

1 192.168.2.5.0 # while it should be 1 0 192.168.2.5
1 1 0.0.0.0
1 2 0.0.0.0
1 3 0.0.0.0
. . .
. . .
. . .
1 254 0.0.0.0

The problem happenes only with the first line, while there is no problem when the other lines are changed by the code. I tried my best to solve this problem but I faild.

Regards
Bassam
 
Old 02-09-2004, 06:42 AM   #10
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
The dot(s) in the ip numbers are seen as special characters during the (sed) search and causes a false hit (although there is a correct hit in the same line) during the replace sed tries to do.

If your searchstring is 0.0.0.0 and the line to search is 1 0 0.0.0.0 the wrong part of the string is found (1 0 0.0.0.0) instead of 1 0 0.0.0.0. Sed sees the dot(s) in the searchstring as being special (any or no character).

The easiest way to remedy this is to place a $ at the end of the searchstring (this tells sed that the string should be at the end of the line). But this only works if there isn't anything after the ip number:

Inputfile:

0 0 1.2.3.4
0 0 1.2.3.4 temporary

If your input looks like the first line, the sollution will work, if it looks like the second line it will not.

You need to change the following (add the bold part) to make this sollution work:

OLD_LINE=$(sed -n "${LI_NO}p" ${INFILE})
sed "${LI_NO}s/${OLD_VAL}$/${NEW_VAL}/1" ${INFILE} > ${TMPFILE}
cp ${TMPFILE} ${INFILE}

The other (better) solution is to give sed the correct searchstring to work with (0\.0\.0\.0 instead of 0.0.0.0).

By 'escaping' a special character (placing a backslash in front of it), you tell the shell that the character should not be seen as special.

Only thing you need to change is the following:
OLD_VAL=$1
to
OLD_VAL="`echo $1 | sed 's/\./\\\./g'`"

s/\./\\\./g substitute a real dot (\.) with \. and do this global on the whole line. You might wonder why I used three /'s (\\\.). The dot is a special character (which I need to escape[\.]), but the backslash is also a special character, which I also need to escape [\\]. Put these two together and you will end up with \\\..

Hope this helps.
 
Old 02-26-2004, 12:18 AM   #11
Bassam
Member
 
Registered: Mar 2003
Location: Malaysia
Posts: 63

Original Poster
Rep: Reputation: 15
Hello Druuna,
For the same text file, how can I read the third field exactly by using the sed instruction???

Ok, first I have to locate the first record (line) number that doesn't contain the data 0.0.0.0 by using:

LI_NO=$(sed -n "/0.0.0.0/!=" ${INFILE} | sed -n '1p')
if [[ ${LI_NO} != "" ]]
then
# The following instruction will assign the located line to the variable
# OLD_LINE.
# But I want to assign only the third part (field) of the line to that
# variable, so how can I do this????
OLD_LINE=$(sed -n "${LI_NO}p" ${INFILE})
fi
 
Old 02-26-2004, 04:08 AM   #12
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
I would not use sed if you want a specific field, awk is the better choice. It can be done using sed, but why make your life harder then necessary.

There seems to be a space (tab) between the fields, so piping it to awk '{ print $3 }' should work.

Replacing
OLD_LINE=$(sed -n "${LI_NO}p" ${INFILE})
with:
OLD_LINE="`echo $LI_NO | awk '{ print $3}'`"

This leaves you with 0.0.0.0 (third field) as value for $OLD_LINE.

Last edited by druuna; 02-26-2004 at 12:30 PM.
 
  


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 On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to find and change a specific text in a text file by using shell script Bassam Programming 1 07-18-2005 07:15 PM
cutting down contents of text file kam_kenneth Linux - Newbie 2 05-22-2004 01:16 AM
tar from contents of a text file trpn Linux - General 3 03-08-2004 01:05 AM
Read contents of file and execute command cosiek Programming 3 09-30-2003 11:07 AM
Change from Read only to Read Write File System? justiceisblind Linux - Newbie 3 03-03-2002 07:23 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

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