LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   appending to the current line in a file instead of creating a new line (https://www.linuxquestions.org/questions/linux-newbie-8/appending-to-the-current-line-in-a-file-instead-of-creating-a-new-line-872423/)

jr950 04-01-2011 12:14 PM

appending to the current line in a file instead of creating a new line
 
Hi; this is a very basic question, I think:

I am combining data from a couple different input files and creating an output file in a specific format.

I notice that if I use the >> operator, information gets appended to a new line in my output file.

This is useful, but if I'd like to append onto the CURRENT line, is there an easy way to do this? I've been googling around and see lots of complicated answers, nothing that suggests to me an easy way to do this.

For example, if my output file looks like this:
b1a:] cat test
hello my name is
b1a:]

and I'd simply like to append "Bob", how can I do it? If I use
b1a:] echo Bob >> test
b1a:] cat test
b1a:] hello my name is
Bob
b1a:]

So what I would prefer is some command that would create the result:

hello my name is Bob


any ideas?

Thanks!

David the H. 04-01-2011 12:59 PM

No, regular redirection won't work here. You need either some fancier scripting or an external tool. Try sed:
Code:

sed -i '$ s/.*/& Bob/' file
-i option edits the original file directly
$ matches the last line of the file
s/// replaces the first with the second string
.* matches the whole line
& inserts the matched pattern into the replacement string
Don't forget the space between them!

crts 04-01-2011 01:10 PM

Hi,

if you simply want to append at the end of the last line then David's solution can be even shortened to just:
Code:

sed -i '$ s/$/ Bob/' file

David the H. 04-01-2011 01:32 PM

Thanks crts. I should've thought of that. :doh:

$ in this case means "end of line", so just replace it with the desired string.

Here's a bash-only version I just thought of, assuming the file is of a reasonable size.
Code:

f="$(<file.txt)" ; echo "${f%$'\n'} Bob" >file.txt
f="$(<file.txt)" imports the whole file into a variable.
echo "${f%$'\n'} Bob" removes the final newline*, if it exists, and tacks on your replacement text.
>file.txt overwrites the original file with your replacement.

* This is an example of parameter substitution and the $'..' extended quoting pattern, which expands backslashed special characters like \n "newline" into their literal ascii characters. It requires the extquote shell option to be enabled, but this is the default.

jr950 04-01-2011 01:59 PM

Wow, thanks for the solution - works very well, thank you!

jr950 04-01-2011 03:36 PM

Actually, the solution
sed -i '$ s/$/ Bob/' file
still leaves me in a bit of a quandary.

This is great if the text to append is a static string like Bob. But if the text I'd like to append on the current line comes from another variable, let's say $appendThis, it breaks down.

For example

b1a:] echo Hello my name is > newFile
b1a:] cat newFile
Hello my name is
b1a:] appendThis=Bob
b1a:] sed -i '$ s/$/ $appendThis/' newFile
b1a:] cat newFile
Hello my name is $appendThis


of course, I'd like the contents of newFile to contain
Hello my name is Bob
and not
Hello my name is $appendThis.

Any ideas?

Thanks!

colucix 04-01-2011 03:45 PM

The single quotes around the sed command prevent the shell's variable substitution. Until there are not special characters whose expansion is permitted inside double quotes, you can try:
Code:

sed "$ s/$/ $append/" file
Remember that "using double quotes the literal value of all characters enclosed is preserved, except for the dollar sign, the backticks (backward single quotes, ``) and the backslash" (from the Bash Guide for Beginners). In this case the dollar signs in the sed address and in the regular expression are not expanded, since they are not associated to something recognizable by the shell. The first $ is followed by a blank space, the second one is followed by / and these combinations have not special meanings for the shell.

jr950 04-01-2011 03:48 PM

Yep, that did the trick. Thanks!

David the H. 04-02-2011 04:03 PM

Also be aware of possible conflicts with sed's delimiters. If the phrase you're trying to replace contains any / characters, it will break the command.

You can avoid this by using a less common delimiter. Sed can accept any single-byte ascii character as a delimiter, so instead of s/x/y/, you can use s|x|y|, or s^x^y^, etc. Just choose one that's unlikely to exist in your input string.

(see man 7 ascii for a full list of ascii characters).

Or use the bash code I gave you instead. It doesn't suffer this kind of problem.

jr950 04-08-2011 03:06 PM

Guess I speak too soon on some occasions.

@colucix: your solution actually prints the desired output to the screen rather than appending to the fire as desired. It also seems to insert an undesired space between the newly appended string and the text originally on the line.

@David the H: your solution (very nearly) works. It appends the text, but it also inserts an undesired space (I checked both the original text and the text to be appended, and neither contained either a leading or trailing space; the space was inserted upon appending). Also, my ouput file will grow to be quite large. Don't know yet if this will become a problem yet, as I haven't run it on real data yet.

Thanks?

jr950 04-08-2011 03:25 PM

There is an additional problem with @David the H's bash-only version. If I'd previously inserted a newline so that when I append to the file, I'd expect the appended text to be appended to the new line, the command given deletes newlines that I'd previously intentionally added.

Here's a full example

b1a] fileName=file.txt
b1a] echo HelloMyNameIs > $fileName
b1a] cat $fileName
HelloMyNameIs
b1a] echo >> $fileName
b1a] cat $fileName
HelloMyNameIs

b1a] appendThis=Bob
b1a] f="$(<$fileName)" ; echo "${f%$'\n'} $appendThis" >$fileName
b1a] cat $fileName
HelloMyNameIs Bob

In this case, I'd like the resulting file to contain text that looks like this:
cat $fileName
HelloMyNameIs
Bob

Any ideas welcome!

colucix 04-08-2011 04:01 PM

Quote:

Originally Posted by jr950 (Post 4318378)
@colucix: your solution actually prints the desired output to the screen rather than appending to the fire as desired. It also seems to insert an undesired space between the newly appended string and the text originally on the line.

You don't really think I could give you a command that actually modifies the content of the file without testing it?!? ;) To actually change the file content use the -i option of sed. Regarding the extra space, I cannot see where does it come from. Please, can you post a real example?

jr950 04-08-2011 04:09 PM

@colucix: I posted a real example just above your post (see today, #11). Just replace the line:

f="$(<$fileName)" ; echo "${f%$'\n'} $appendThis" >$fileName

with a different idea!

colucix 04-08-2011 04:21 PM

Pardon me but still I cannot see what is the undesired space you mentioned. Here is my example:
Code:

$ cat newFile
Hello my name is
$ append=Bob
$ echo $append
Bob
$ sed "$ s/$/ $append/" newFile
Hello my name is Bob

in this case I intentionally put a space to separate words. Otherwise I would get:
Code:

sed "$ s/$/$append/" newFile
Hello my name isBob


jr950 04-08-2011 04:28 PM

Hi @colucix. Using the -i flag and removing the space, the solution works. Thanks.

I also found a result within an old posting in a similar thread; answer provided by Zulfilee:

http://www.linuxquestions.org/questi...4/#post2299440

Thanks.


All times are GMT -5. The time now is 06:36 PM.