Add comment on last line if found match


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Add comment on last line if found match
# 1  
Old 12-05-2017
Add comment on last line if found match

Hi All,

totally new on it , normally use it for just 1 line.
i'm looking for help.

i'm have 2 file.

file 1 :
Code:
-------------------------------------------------- 
c12
c1
c3
--------------------------------------------------

file 2:
Code:
other content 
--------------------------------------------------
 test "analog/c12" 
 test "analog/c13"
 test "analog/c1"
other content.
--------------------------------------------------

expected output.
file 3:(if possible direct change at file 2)
Code:
--------------------------------------------------
other content 
 test "analog/c12"   ! comment 
 test "analog/c13"
 test "analog/c1"     ! comment
other content.
-------------------------------------------------




other question is:
if using awk , how to search at get data from file1 and store as variable for using at file 2.

Last edited by Don Cragun; 12-05-2017 at 03:49 AM.. Reason: Turn off parsing of text being printed as a smiley.
# 2  
Old 12-05-2017
Having two input files and hoping to get a third output file with no explanation of the logic to be used to make those changes is not at all likely to get you what you want.

Please tell us what operating system you're using.

Please tell us what shell you're using.

Please clearly explain exactly what text should be added to file 2 when certain conditions are met.

Please clearly explain exactly what conditions need to occur to cause a change to be made to file 2.

Note that putting <space>, <tab>, or (especially) <newline> characters in a filename makes it less likely that people writing scripts to use your file will actually handle your file correctly.
# 3  
Old 12-05-2017
thank you for reply.

OS
window 7 and window xp, using korn shell.

text need at at file 2 if meet the condition is > <space><space>!<space>comment<space>comment at the end of the line.

condition:
if found at file 1 if the line have match at file 2 then add comment.
exp:
file 1: have c12 , then search at file 2 , if found test "analog/c12" then modify this line at file 2, and so on.
# 4  
Old 12-05-2017
Making quite some assumtions as window's awk's version's capabilities are not known (to me), nor is the pattern to search (is "analog/" compulsory?), nor WHAT to add (post#1 and #2 info don't match), nor does the thread title match its contents, would this come close to what you want?
Code:
awk 'NR==FNR {if (!/^--/) T[$1]; next} $3 in T {$0 = $0 "  ! comment"} 1' file1 FS='[/"]' file2
other content 
--------------------------------------------------
 test "analog/c12"   ! comment
 test "analog/c13"
 test "analog/c1"  ! comment
other content.
--------------------------------------------------

As you can see, a correct and detailed specification helps avoid ambiguities and keeps people from guessing. Be way more precise and specific in the future!
# 5  
Old 12-05-2017
I agree with RudiC that your specification doesn't match the thread title and doesn't match the output you specified in post #1 in this thread. And you haven't said, since you're working on Windows, whether the input files you're using are UNIX text files or DOS text files. The following should work no matter which type of text file you have and produce the same type of output in file 2 that it found in the the original file 2. But, of course, it is making lots of assumptions based on your conflicting requirements. (Note that I still think it is a horrible idea to use filenames containing <space> characters. but this script uses the filenames you specified in post #1.
Code:
#!/bin/ksh
awk '
{	# Get rid of <carriage-return> at end of line if there
	# is one.  Set cr to <carriage-return> if there was one; otherwise
	# set it to an empty string.
	cr = sub(/\r$/, "") ? "\r" : ""
}
FNR == NR {
	# For all lines in the first input file...
	# Set a search string as an index in the add_com[] array corresponding
	# to this input line.
	add_com["test \"analog/" $0 "\""]
	next
}
{	# For all lines in the second input file, look for a match in add_com[].
	for(i in add_com)
		if(index($0, i)) {
			# Match found.
			# Set this line in the output buffer to include a
			# comment and put back the <carriage-return> if there
			# was one.
			o[FNR] = $0 "  ! comment" cr
			# Note that a modification was made.
			mod = 1
			next
		}
	# No match found.
	# Copy this line to output buffer unchanged (restoring the
	# <carriage-return> if there was one).
	o[FNR] = $0 cr
}
END {	# If any changes were made, copy the new contents of the second file
	# back into that file.
	if(mod)
		for(i = 1; i <= FNR; i++)
			print o[i] > FILENAME
}' "file 1" "file 2"

Note that when you store the above script in a file in Windows, you absolutely must make the text in this file be in UNIX text file format with no <carriage-return> characters in the file. If the location of the Korn shell on Windows is not /bin/ksh, you'll need to change the end of the first line of the script to an absolute path to its location on your systems.
# 6  
Old 12-05-2017
Quote:
Originally Posted by Don Cragun
I agree with RudiC that your specification doesn't match the thread title and doesn't match the output you specified in post #1 in this thread. And you haven't said, since you're working on Windows, whether the input files you're using are UNIX text files or DOS text files. The following should work no matter which type of text file you have and produce the same type of output in file 2 that it found in the the original file 2. But, of course, it is making lots of assumptions based on your conflicting requirements. (Note that I still think it is a horrible idea to use filenames containing <space> characters. but this script uses the filenames you specified in post #1.
Code:
#!/bin/ksh
awk '
{	# Get rid of <carriage-return> at end of line if there
	# is one.  Set cr to <carriage-return> if there was one; otherwise
	# set it to an empty string.
	cr = sub(/\r$/, "") ? "\r" : ""
}
FNR == NR {
	# For all lines in the first input file...
	# Set a search string as an index in the add_com[] array corresponding
	# to this input line.
	add_com["test \"analog/" $0 "\""]
	next
}
{	# For all lines in the second input file, look for a match in add_com[].
	for(i in add_com)
		if(index($0, i)) {
			# Match found.
			# Set this line in the output buffer to include a
			# comment and put back the <carriage-return> if there
			# was one.
			o[FNR] = $0 "  ! comment" cr
			# Note that a modification was made.
			mod = 1
			next
		}
	# No match found.
	# Copy this line to output buffer unchanged (restoring the
	# <carriage-return> if there was one).
	o[FNR] = $0 cr
}
END {	# If any changes were made, copy the new contents of the second file
	# back into that file.
	if(mod)
		for(i = 1; i <= FNR; i++)
			print o[i] > FILENAME
}' "file 1" "file 2"

Note that when you store the above script in a file in Windows, you absolutely must make the text in this file be in UNIX text file format with no <carriage-return> characters in the file. If the location of the Korn shell on Windows is not /bin/ksh, you'll need to change the end of the first line of the script to an absolute path to its location on your systems.
Thank you for reply , it work.

Sorry for not clear explanation given.
i'm a test engineer , sorry not very clear about unix script, i'm looking for for help due to my system running at window with kornshell base.

i have try it , few way search website before post.

1.
i'm looking on how it work on 2 file.
may i know more clear on this :
}' "file 1" "file 2"
2.
may i know is that awk are reading from top to bottom file ?
if this 2 awk, is that it finish the 1st 1 before go to second ?
awk '
{
content
}

awk '
{
content
}



most of the example given are just 1 file on internet.
# 7  
Old 12-06-2017
You can find lots of examples in the UNIX & Linux Forums of awk scripts that work on two or more input files and that produce two or more output files (although we don't need to do the latter in this case).

In an awk program, each group of statements is of the general form:
Code:
condition { action }

Before any lines are read from any of the input files named as operands, the commands specified in the actions of all groups with the condition BEGIN (if there are any) are executed in the order in which they appear in the awk program. There aren't any BEGIN sections in my code for this thread.

After all files of the input files named as operands have been processed, all commands specified in the actions of all groups with the condition END (if there are any) are executed in the order in which they appear in the awk program.

All other groups are processed in the order in which they appear in the awk program for every record (with default options, each input line in each file is a record) is processed. If the condition for a group evaluates to a non-zero numeric value or to a non-empty string string value (i.e., evaluates to TRUE), the statements in the action for that group are executed in order; otherwise the statements in that group are skipped for that input record. If there is no condition at the start of a group, the commands in the action in that group are always executed. If the condition evaluates to TRUE and the action and braces ({ and }) are omitted, a default action of print (which prints the current state of the current input record) is performed.

I will assume that you can read the manual page on for awk (by giving the command man awk at a ksh primary prompt in your shell window) to see what the standard awk variables, functions, and statements do. I would hope that the comments I supplied in each group explain what that group is trying to do.

The first group:
Code:
{	# Get rid of <carriage-return> at end of line if there
	# is one.  Set cr to <carriage-return> if there was one; otherwise
	# set it to an empty string.
	cr = sub(/\r$/, "") ? "\r" : ""
}

(with no condition is executed for every record read from both input files and does exactly what the comments say it does.

The second group:
Code:
FNR == NR {
	# For all lines in the first input file...
	# Set a search string as an index in the add_com[] array corresponding
	# to this input line.
	add_com["test \"analog/" $0 "\""]
	next
}

is executed when the condition FNR == NR evaluates to TRUE. It evaluates to TRUE when the Number of Records read from the current File (FNR) is equal to the Number of Records read from all files (NR) which happens when any line from the 1st input file is being processed. The next statement in this action causes all remaining statements in the current action (if there are any) and in any following groups to be skipped for this input record, causes the next available input record to be read, and starts processing groups in order for that new input record. The combination of the action and the next statement guarantee that the following group will not be performed for records read from the 1st input file.

The third group:
Code:
{	# For all lines in the second input file, look for a match in add_com[].
	for(i in add_com)
		if(index($0, i)) {
			# Match found.
			# Set this line in the output buffer to include a
			# comment and put back the <carriage-return> if there
			# was one.
			o[FNR] = $0 "  ! comment" cr
			# Note that a modification was made.
			mod = 1
			next
		}
	# No match found.
	# Copy this line to output buffer unchanged (restoring the
	# <carriage-return> if there was one).
	o[FNR] = $0 cr
}

even though there is no condition is only executed for input files after the 1st input file (and in this code there are only two input files). This group copies the input records as they are read into an output buffer array (o[]) with the index in the array being the current input file record number after searching for and updating any lines that contain the key strings created from lines found in the 1st input file.

The fourth group:
Code:
END {	# If any changes were made, copy the new contents of the second file
	# back into that file.
	if(mod)
		for(i = 1; i <= FNR; i++)
			print o[i] > FILENAME
}

with the action END (as described before) evaluates to FALSE for every line read from the two input files and is only processed after end-of-file is reached on both input files. As noted in the comments, this group copies the accumulated output buffer back into the last input file. The number of lines found in the last input file (FNR) and the pathname of the last input file (FILENAME) remain valid during any END actions.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Modify text file if found multiple pattern match for every line.

Looking for help, i have input file like below and want to modify to expected output, if can without create additional file, hope can direct modify it. have 2 thing need do. 1st is adding a word (testplan generation off) after ! ! IPG: Tue Aug 07 14:31:17 2018 2nd is adding... (16 Replies)
Discussion started by: kttan
16 Replies

2. Shell Programming and Scripting

How to print the entire line if the mentioned match is found?

Hello Everyone, I have a file with 5 fields in each line just like mentioned below. Also the 4th field is time elapsed(hh:mm:ss) since the process is running xyz abc status 23:00:00 idle abc def status 24:00:00 idle def gji status 27:00:02 idle fgh gty status 00:00:00 idle Here I... (8 Replies)
Discussion started by: rahul2662
8 Replies

3. Shell Programming and Scripting

Displaying text till pattern match found in a line

Hi All, From the below line if we want to display all the text till found pattern dot/. I was trying with the below code but couldn't able to print text before the pattern. it display texts which is found after pattern. awk '/assed/{print;getline;print}' file_name | sed 's/^*. *//' input... (4 Replies)
Discussion started by: Optimus81
4 Replies

4. UNIX for Dummies Questions & Answers

Display n lines after match found and other line

I have a file like this DoctorName Address1 Address2 DOB InsuredName Address1 Address2 DOB PatientName Address1 Address2 DOB ClaimNo1 DoctorName Address1 Address2 DOB InsuredName (2 Replies)
Discussion started by: nsuresh316
2 Replies

5. UNIX for Dummies Questions & Answers

awk display the match and 2 lines after the match is found.

Hello, can someone help me how to find a word and 2 lines after it and then send the output to another file. For example, here is myfile1.txt. I want to search for "Error" and 2 lines below it and send it to myfile2.txt I tried with grep -A but it's not supported on my system. I tried with awk,... (4 Replies)
Discussion started by: eurouno
4 Replies

6. Shell Programming and Scripting

add line and remove comment in some script

Hi, i need some help. i am not sure about my idea. I have a script directory under my home directory,which has a lot of scripts in it. These are some names of the scripts in /axxhome/prdv/script aly300.sh axt300.sh arv300.sh clp300.sh ctth300.sh aly400.sh axt400.sh arv400.sh... (6 Replies)
Discussion started by: debu000
6 Replies

7. Shell Programming and Scripting

help with script to send email and if subject line match is found

Help with script that will check log, then find a match is found, add that as the subject line. 1. The script will always run as a deamon.. and scan the event.log file 2. when a new 101 line is added to the event.log file, have the script check position 5,6 and 7 which is the job name, which... (2 Replies)
Discussion started by: axdelg
2 Replies

8. Shell Programming and Scripting

Need one-liner to look for a line and add it if not found

I need a good one-liner to look in a specific text file for a line of text and if it's not found, add it at the bottom of the file. Perl, sed, not particular, whatever works. To make matters worse, the line of text is in a config script with lots of special characters and needs lots of... (3 Replies)
Discussion started by: brendaT
3 Replies

9. Shell Programming and Scripting

if match found go to a particular line in perl

Hello Experts, I am newbie to perl, just curious to know how to do the following in perl. suppose I ve a txt file like below. when it founds "*Main Start" Then go to "*Main End,,,,,,,," patteren and just collect the number from the previous line of "*Main End,,,,,,," pattern . In my... (17 Replies)
Discussion started by: user_prady
17 Replies

10. Shell Programming and Scripting

Need to add a comment line in a text file

Hi I need to add a comment line at the begining of a text file. The scenario is given below. 1. The number of servers that needs to be updated is around 80 2. The location of the text file in all the servers are the same including the file name. 3. The comment has to be added at the very... (2 Replies)
Discussion started by: orakhan
2 Replies
Login or Register to Ask a Question