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 |
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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
|
|
01-26-2004, 01:37 AM
|
#1
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Rep:
|
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
|
|
|
01-26-2004, 04:48 AM
|
#2
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
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.
|
|
|
01-26-2004, 05:16 AM
|
#3
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
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
|
|
|
01-26-2004, 05:39 AM
|
#4
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
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.
|
|
|
01-26-2004, 06:39 AM
|
#5
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
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.
|
|
|
01-26-2004, 08:21 AM
|
#6
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
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
|
|
|
01-26-2004, 08:22 AM
|
#7
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
so I need your help about the second issue
|
|
|
02-08-2004, 10:05 PM
|
#9
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
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
|
|
|
02-09-2004, 06:42 AM
|
#10
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
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.
|
|
|
02-26-2004, 12:18 AM
|
#11
|
Member
Registered: Mar 2003
Location: Malaysia
Posts: 63
Original Poster
Rep:
|
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
|
|
|
02-26-2004, 04:08 AM
|
#12
|
LQ Veteran
Registered: Sep 2003
Posts: 10,532
|
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.
|
|
|
All times are GMT -5. The time now is 04:56 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|