DaemonForums  

Go Back   DaemonForums > Miscellaneous > Programming

Programming C, bash, Python, Perl, PHP, Java, you name it.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 6th November 2010
guitarscn guitarscn is offline
Package Pilot
 
Join Date: Oct 2008
Posts: 166
Default How to append text to second line of a file

Say for example I have a text file like:

Code:
1
3
4
How would I append "2" to the second line of this file from the command line? (ksh here) I tried using some combinations of head/tail but I'm not very good
Reply With Quote
  #2   (View Single Post)  
Old 6th November 2010
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

The correct way depends on whether you want to edit the file or create a new file with the append.

If you want the same file to become

Code:
1
3 2
4
Use an ed script and invoke it from your ksh script.

Something like this should work:
Code:
Terry@vectra$ cat > testfile
1
3
4
Terry@vectra$ ed -s testfile << EOF
> 2
> a
>  2
> .
> 2,3j
> wq
> EOF
2
Terry@vectra$ cat testfile
1
3 2
4
Terry@vectra$
That ed script reads:
  1. Go to line #2
  2. Append text.
  3. ' 2' is the text to append; the single . means you're done appending.
  4. join lines 2 and 3. (Note that ed does not add or remove any whitespace on it's own!)
  5. write file and quit ed.

If you're not particularly familiar with interactive work, the '>' is my shells $PS2, used for such cases; so you don't type it in a ksh script. Like wise the << EOF thing is called a here document.

In a shell script, it would look like this:

Code:
ed -s testfile << EOF
2
a
2
.
2,3j
wq
EOF
# rest of your shell scripts code here

If you want a new file with the edits, you'll have to get a little creative with pipe lines and some of the tools for joining lines. You could also replace the ed script with an ex script, thus allowing an easier "Save as" like command to be used but the portability of ex script varies by the users competency for portability. ed scripts on the other hand are pretty darn universal.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
  #3   (View Single Post)  
Old 6th November 2010
BSDfan666 BSDfan666 is offline
Real Name: N/A, this is the interweb.
Banned
 
Join Date: Apr 2008
Location: Ontario, Canada
Posts: 2,223
Default

Well, it's not exactly a "script" but lam(1) works for this.

Code:
$ cat file.txt
1
3
4
$ echo "\n 2" | lam file.txt -
1
3 2
4
$
It should be worth noting that lam(1) is probably a BSD thing, it's not mentioned in the SUS/POSIX specifications.. paste(1) may be the standards alternative.
Reply With Quote
  #4   (View Single Post)  
Old 7th November 2010
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

For standards compliance you would want to look at some of the usual but less well known text manipulation tools:

Code:
comm	select or reject lines common to two files	http://www.opengroup.org/onlinepubs/9699919799/utilities/comm.html
csplit	split files based on context	http://www.opengroup.org/onlinepubs/9699919799/utilities/csplit.html
cut	cut out selected fields of each line of a file	http://www.opengroup.org/onlinepubs/9699919799/utilities/cut.html
fold	filter for folding lines	http://www.opengroup.org/onlinepubs/9699919799/utilities/fold.html
join	relational database operator	http://www.opengroup.org/onlinepubs/9699919799/utilities/join.html
paste	merge corresponding or subsequent lines of files	http://www.opengroup.org/onlinepubs/9699919799/utilities/paste.html
split	split files into pieces	http://www.opengroup.org/onlinepubs/9699919799/utilities/split.html
Later 4.x BSD systems expanded on such things quite plentifully, if FreeBSD is any example, hehe.

I have a file in my Dropbox that lists most of the programs covered by the last SUS spec, sans SCCS, things that should be built into the shell, etc.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
  #5   (View Single Post)  
Old 7th November 2010
rocket357's Avatar
rocket357 rocket357 is offline
Real Name: Jonathon
Wannabe OpenBSD porter
 
Join Date: Jun 2010
Location: 127.0.0.1
Posts: 429
Default

sed is my choice for stuff like this:

Code:
rocket357@SkyNet:~$ cat test.txt
1
3
4

rocket357@SkyNet:~$ sed 2's/\(.*\)/\1 <additional text>/' test.txt
1
3 <additional text>
4
but that's just me. I like sed and use it perhaps too much.
Reply With Quote
  #6   (View Single Post)  
Old 7th November 2010
drl's Avatar
drl drl is offline
Port Guard
 
Join Date: May 2008
Posts: 19
Default

Hi.

Here is an alternate method for sed, as well as an awk solution. The center code is the important part, the beginning lines are to show the environment of execution:
Code:
#!/usr/bin/env bash

# @(#) s2       Demonstrate append string to specific line with awk, sed.

# Section 1, setup, pre-solution.
# Infrastructure details, environment, commands for forum posts. 
# Uncomment export command to test script as external user.
# export PATH="/usr/local/bin:/usr/bin:/bin"
set +o nounset
pe() { for i;do printf "%s" "$i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
C=$HOME/bin/context && [ -f $C ] && . $C sed
awk -V
set -o nounset
pe

FILE=${1-data1}

# Section 2, display input file.
# Display sample of data file, with head & tail as a last resort.
pl " Contents of data file $FILE:"
cat $FILE

# Section 3, solution.
pl " Results, awk:"
awk '
NR == 2 { print $0, 2; next }
        { print }
' $FILE

pl " Results, sed:"
sed '2s/$/ 2/' $FILE

exit 0
producing:
Code:
% ./s2

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: OpenBSD, 4.2, i386
GNU bash 3.2.17
sed - ( /usr/bin/sed Aug 28 2007 )
awk version 20041222


-----
 Contents of data file data1:
1
3
4

-----
 Results, awk:
1
3 2
4

-----
 Results, sed:
1
3 2
4
Best wishes ... cheers, drl
Reply With Quote
  #7   (View Single Post)  
Old 7th November 2010
Oko's Avatar
Oko Oko is offline
Rc.conf Instructor
 
Join Date: May 2008
Location: Kosovo, Serbia
Posts: 1,102
Default

Quote:
Originally Posted by rocket357 View Post
sed is my choice for stuff like this:

Code:
rocket357@SkyNet:~$ cat test.txt
1
3
4

rocket357@SkyNet:~$ sed 2's/\(.*\)/\1 <additional text>/' test.txt
1
3 <additional text>
4
but that's just me. I like sed and use it perhaps too much.
One more vote for sed
Reply With Quote
  #8   (View Single Post)  
Old 7th November 2010
rocket357's Avatar
rocket357 rocket357 is offline
Real Name: Jonathon
Wannabe OpenBSD porter
 
Join Date: Jun 2010
Location: 127.0.0.1
Posts: 429
Default

Quote:
Originally Posted by drl View Post
sed '2s/$/ 2/' $FILE
Ahh yes, much more efficient (and easier to type) than matching the entire line. Thanks for pointing this out.
Reply With Quote
  #9   (View Single Post)  
Old 8th November 2010
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

SED is a stream oriented version of ED .

The problem is, sed doesn't work like ed for editing files, which results in $ sed -e 'expr' infile > outfile instead of simply editing the file in place, and the only time you can rely on sed being able to edit a file in place is when it is GNU SED or a specific operating system that supports a comparable feature.

Which means for portability reasons, if you're editing in place, ed and perl are your winners.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 8th November 2010
drl's Avatar
drl drl is offline
Port Guard
 
Join Date: May 2008
Posts: 19
Default

Hi.

My take on this is that the in-place options on most utilities are something of a misnomer. The data is written to a scratch file, then copied back onto the original -- one does not get something for nothing. This is true of "-i" on GNU sed, as well as the interactive editors ed/ex. So that the in-place description refers to the result rather than the method.

To be sure, in place options are useful devices for convenience, but one could as easily use sed/awk with a utility like sponge: http://linux.die.net/man/1/sponge , part of moreutils, source at http://kitenet.net/~joey/code/moreutils/ , or write a scratch file oneself.

There are times when I use the interactive editors ex/ed in scripting mode, but it's far more often as a demonstration that it can be done, rather than to do it in practice.

The operation of ed/ex compared to sed/awk is different in the sense that -- at least with sed -- most often a line is read in, operated upon, and written out. The ed/ex editors will read in the entire file (possibly making an index of the locations of the lines on a scratch file), so that the memory demands can be significant.

In most of the situations I have seen, sed/awk is far more often used than is ed/ex for scripting tasks. However, when the file is small enough and certain requirements are present -- such as addressing a line before a line that matches a pattern -- then ed/ex can be quite useful.

There are adherents of sed on comp.unix.shell, but I think the flexibility and speed of GNU awk makes it a tool that one finds oneself reaching for more often than for sed. For the everyday tasks of dealing with fields of data, I have not found a more useful utility than awk.

For mimicking the data-tool-connecting philosophy of *nix, I have found perl better, in that it deals with command-line options better than does awk. For example, the module Getopt::Euclid automatically will produce documentation and an option parser from one set of documentation sequences (POD mark-up). Externally, then, one could ask for
Code:
perl-script-name --man
to get man-style documentation, and the code will also parse command-line options.

Best wishes ... cheers, drl

( Edit 1: typo )

Last edited by drl; 8th November 2010 at 10:46 AM.
Reply With Quote
Old 8th November 2010
s0xxx's Avatar
s0xxx s0xxx is offline
Package Pilot
 
Join Date: May 2008
Posts: 192
Default

Quote:
Originally Posted by drl View Post
My take on this is that the in-place options on most utilities are something of a misnomer. The data is written to a scratch file, then copied back onto the original -- one does not get something for nothing. This is true of "-i" on GNU sed, as well as the interactive editors ed/ex. So that the in-place description refers to the result rather than the method.
I fully agree.

Anotha' (similar) awk solution:
Code:
$ cat file
1
3
4

$ awk 'NR==2{$0=$0" 2"}1' file
1
3 2
4
__________________
The best way to learn UNIX is to play with it, and the harder you play, the more you learn.
If you play hard enough, you'll break something for sure, and having to fix a badly broken system is arguably the fastest way of all to learn. -Michael Lucas, AbsoluteBSD
Reply With Quote
Old 8th November 2010
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

Point being, you have to write your own w command in shell script when using sed, and some people choose to for awk as well.. Which means dealing with temporary files by hand. For those who think it's simple, $ command file > file.bak && mv file.bak file is not perfect for every situation.

You know, fewer moving parts the fewer things that can break.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 8th November 2010
BSDfan666 BSDfan666 is offline
Real Name: N/A, this is the interweb.
Banned
 
Join Date: Apr 2008
Location: Ontario, Canada
Posts: 2,223
Default

There is no right way to do things, it's just a matter of preference.. use what's available.
Reply With Quote
Old 8th November 2010
rocket357's Avatar
rocket357 rocket357 is offline
Real Name: Jonathon
Wannabe OpenBSD porter
 
Join Date: Jun 2010
Location: 127.0.0.1
Posts: 429
Default

Quote:
Originally Posted by TerryP View Post
You know, fewer moving parts the fewer things that can break.
I think the point drl was getting at is that just because those moving parts are "behind the scenes" doesn't mean they don't exist. Is it harder to screw with it and mess stuff up if you can't see it? Sure...but that doesn't mean a well-written script is more prone to failure just because it doesn't hide the steps from you.
Reply With Quote
Old 8th November 2010
thirdm thirdm is offline
Spam Deminer
 
Join Date: May 2009
Posts: 248
Default

Quote:
Originally Posted by BSDfan666 View Post
There is no right way to do things, it's just a matter of preference.. use what's available.

emacs --batch -Q --file file.dat --eval '(when (zerop (forward-line)) (end-of-line) (insert " 2") (save-buffer))'
Reply With Quote
Old 9th November 2010
TerryP's Avatar
TerryP TerryP is offline
Arp Constable
 
Join Date: May 2008
Location: USofA
Posts: 1,547
Default

Quote:
Originally Posted by rocket357 View Post
I think the point drl was getting at is that just because those moving parts are "behind the scenes" doesn't mean they don't exist. Is it harder to screw with it and mess stuff up if you can't see it? Sure...but that doesn't mean a well-written script is more prone to failure just because it doesn't hide the steps from you.

It's a question of responsibility, do you trust your copy/paste drill over an existing program? Why should you reimplement the same exact moving parts in shell, for each script you would want to make such a change in - when you have a tried and tested tool for doing it that has existed for over 35 years. It's just a waste of time. Coding hours should be spent on things that actually contribute to the program, not a substitute for learning the standard issue stuff.

Quote:
Originally Posted by "7th Commandment of C Programming
Thou shalt study thy libraries and strive not to reinvent them without cause, that thy code may be short and readable and thy days pleasant and productive.
From the perspective of shell scripting, your utilities are much like the libraries of a C program.
__________________
My Journal

Thou shalt check the array bounds of all strings (indeed, all arrays), for surely where thou typest ``foo'' someone someday shall type ``supercalifragilisticexpialidocious''.
Reply With Quote
Old 9th November 2010
rocket357's Avatar
rocket357 rocket357 is offline
Real Name: Jonathon
Wannabe OpenBSD porter
 
Join Date: Jun 2010
Location: 127.0.0.1
Posts: 429
Default

Quote:
Originally Posted by TerryP View Post
It's a question of responsibility, do you trust your copy/paste drill over an existing program?
Relax man, it's emulating an "in-place edit", not writing a kernel module.

And yes, I trust my scripting skills to do the job right. (And no, I'm not saying I don't trust the tried and true code).
Reply With Quote
Reply

Thread Tools
Display Modes

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

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Text to speech (save to file) - text2wave broken godfrank FreeBSD Ports and Packages 2 23rd May 2010 02:13 AM
Text screwed in Qt4 line edits (etc) TerryP FreeBSD Ports and Packages 0 12th November 2009 04:01 AM
avidemux2 command line roddierod FreeBSD General 1 10th November 2008 08:27 PM
shell: how to take part of the line... graudeejs Programming 8 6th September 2008 11:13 PM
TCSH - getting to start of line maxrussell FreeBSD General 3 4th July 2008 11:55 AM


All times are GMT. The time now is 04:27 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick