LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-30-2012, 09:01 AM   #1
mosthated
LQ Newbie
 
Registered: May 2012
Posts: 8

Rep: Reputation: Disabled
Replace line with line from other file, if...


Hi all,

I have two files, that look like this:

file 1)
a data
b data
c location://wrong-path-to-file/filename.mp3
d data
e
f data
g data
h location://wrong-path-to-file/filename.mp3
i data

etc.

file 2)
a no data
b no data
c location://right-path-to-file/filename.mp3
d no data
e
f no data
g no data
h location://right-path-to-file/filename.mp3
i no data

etc.

I want to merge the two files, so that:

new file)
a data
b data
c location://right-path-to-file/filename.mp3
d data

etc.

The files are not the same in layout, so I cannot just select the right lines.

What I'm thinking about is something like this:

if line contains "location" in file 1
then select filename.mp3 using sed/cut /...
search for filename.mp3 in file 2 (assuming the filename is unique)
replace the line in file 1 with the line containg filename.mp3 from file 2

I am wondering if this is possible with bash?

Thanks! M0s..
 
Old 05-30-2012, 01:03 PM   #2
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,715

Rep: Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034
Are the paths in file 2 always correct?

As you have pointed out, what if the filename is not unique?

Are the a, b, c, etc actually in the file or just there to denote each line?

What if the filename you find is not on the same line in the second file as the first file?

As you can see, there seem to be more questions about your question than answers so far
 
Old 05-31-2012, 12:32 AM   #3
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 947Reputation: 947Reputation: 947Reputation: 947Reputation: 947Reputation: 947Reputation: 947Reputation: 947
I think I'm on the same lines as Grail. If we make some assumptions, and use the first field and the filename as an unique key, in awk this would be:
Code:
awk '#
    BEGIN {
        # Accept any newline convention, removing leading and trailing whitespace.
        RS = "[\t\v\f ]*(\r\n|\n\r|\r|\n)[\t\v\f ]*"

        # Fields are separated by one or more consecutive whitespace characters.
        FS = "[\t\v\f ]+"

        # For output, use Unix newline convention.
        ORS = "\n"

        # For output, use space as a field separator.
        # (This only affects when the input record is modified).
        OFS = " "

        # Ordinal for file being accessed (1, 2, ...)
        FILE = 0
    }

    # Increment FILE for each new file.
    (FNR == 1) { FILE++ }

    # For the first file, only location:// lines are remembered.
    (FILE == 1 && $2 ~ /^location:/) {
        # As the key, take the filename part of the location,
        key = $2
        sub(/^.*\//, "", key)
        # but prepend the first field and a space to it.
        key = $1 " " key

        # Do we already have this key used?
        if (key in location)
            if (location[key] != $2)
                printf("Warning: %s redefined from %s to %s.\n", key, location[key], $2) > "/dev/stderr"

        # Save the entire location under the key.
        location[key] = $2
    }

    # A location field in the second file?
    (FILE == 2 && $2 ~ /^location:/) {
        # Construct the key the same way as above.
        key = $2
        sub(/^.*\//, "", key)
        key = $1 " " key

        # If there is a stored location corresponding to key, replace the second field.
        if (key in location)
            $2 = location[key]

        # Note: To retain the original field separator, you can use
        #   sub(/location:[^\t\v\f ]*/, location[key])
    }

    # Output all records for the second file.
    # The "default rule" is { print $0 }; no need to write it.
    (FILE == 2)
    ' locations-but-no-data data-but-wrong-locations > new-file
The awk command is much, much longer than really needed, but I wanted to make it as readable and robust as possible. The first line begins with a comment because some awk variants do not like an empty first line, and I wanted to have it nicely indented.

Running with your example files new-file will contain
Code:
a data
b data
c location://right-path-to-file/filename.mp3
d data
e
f data
g data
h location://right-path-to-file/filename.mp3
i data
Questions?

Last edited by Nominal Animal; 05-31-2012 at 12:33 AM.
 
Old 05-31-2012, 02:49 AM   #4
mosthated
LQ Newbie
 
Registered: May 2012
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks for the answers!

Here are the answers to your questions:

1) Are the paths in file 2 always correct? YES

2) As you have pointed out, what if the filename is not unique? I think I can check that quickly by using find all MP3 files recursively in the parent directory and than use sort unique. For now, I'm pretty sure the all are unique.

Are the a, b, c, etc actually in the file or just there to denote each line? The a, b, c, etc only refer to the lines. They are NOT in the actual file.

What if the filename you find is not on the same line in the second file as the first file? As I said before, the files are not the same in layout, nor in order. Therefore I cannot simply swap line X in file 1 with line X in file 2.

Would this change anything in the script?

Thanks!

M0s..
 
Old 05-31-2012, 09:15 AM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,715

Rep: Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034Reputation: 3034
SO if I am on the right track, something like:
Code:
awk -F/ 'FNR==NR{if(/location/)file[$NF]=$(NF-1);next}$NF in file{$(NF-1)=file[$NF]}1' file2 file1 > new_file
 
  


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



Similar Threads
Thread Thread Starter Forum Replies Last Post
search folders, find a line in a file, and replace it with a new line ithirdeye Programming 2 04-07-2012 04:27 PM
Perl: Match part of a line and replace with another line from the same file briana.paige Linux - Newbie 8 06-27-2009 06:35 AM
how to replace a line in a file with another line. another 1 Linux - Newbie 5 04-11-2009 08:09 AM
how to replace line of file with another line using awk in shell script amit_pansuria Programming 3 03-29-2009 09:43 AM
How to identify a line and replace another string on that line using Shell script? Sid2007 Programming 10 10-01-2007 08:49 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:47 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration