I have created a file named "asd.txt" on a UNIX based system.
I added four lines by using echo command.
Now, I would like to change the first line of this file.
I am not allowed to use any text editors, such as vi.
I have to do this by using only command line. Can anyone help?
Thanks.
Here is how you could do it with sed.
sed '1 s/search/replace/' asd.txt
If you are feeling up to it and have GNU sed, use the -i switch to do it in place.
If you want to replace the entire first line how about doing this?
echo "Here is my new first line" && sed '1d' asd.txt
For both of these commands you can redirect the output to a new file using the > operator.
#!/bin/bash
cat <(echo "Replacement") <(tail -n +2 foo.txt)
Related
I'm trying to write a script to swap out text in a file:
sed s/foo/bar/g myFile.txt > myFile.txt.updated
mv myFile.txt.updated myFile.txt
I evoke the sed program, which swaps out text in myFile.txt and redirects the changed lines of text to a second file. mv then moves .updated txt file to myFile.txt, overwriting it. That command works in the shell.
I wrote:
#!/bin/sh
#First, I set up some descriptive variables for the arguments
initialString="$1"
shift
desiredChange="$1"
shift
document="$1"
#Then, I evoke sed on these (more readable) parameters
updatedDocument=`sed s/$initialString/$desiredChange/g $document`
#I want to make sure that was done properly
echo updated document is $updatedDocument
#then I move the output in to the new text document
mv $updatedDocument $document
I get the error:
mv: target `myFile.txt' is not a directory
I understand that it thinks my new file's name is the first word of the string that was sed's output. I don't know how to correct that. I've been trying since 7am and every quotation, creating a temporary file to store the output in (disastrous results), IFS...everything so far gives me more and more unhelpful errors. I need to clear my head and I need your help. How can I fix this?
Maybe try
echo $updatedDocument > $document
Change
updatedDocument=`sed s/$initialString/$desiredChange/g $document`
to
updatedDocument=${document}.txt
sed s/$initialString/$desiredChange/g $document
Backticks will actually put the entire piped output of the sed command into your variable value.
An even faster way would be to not use updatedDocument or mv at all by doing an in-place sed:
sed -i s/$initialString/$desiredChange/g $document
The -i flag tells sed to do the replacement in-place. This basically means creating a temp file for the output and replacing your original file with the temp file once it is done, pretty much exactly as you are doing.
#!/bin/sh
#First, I set up some descriptive variables for the arguments
echo "$1" | sed #translation of special regex char like . * \ / ? | read -r initialString
echo "$2" | sed 's|[\&/]|\\&|g' | read -r desiredChange
document="$3"
#Then, I evoke sed
sed "s/${initialString}/${desiredChange}/g" ${document} | tee ${document}
don't forget that initialString and desiredChange are pattern interpreted as regex, so a trnaslation is certainly needed
sed #translation of special regex char like . * \ / ? is to replace by the correct sed (discuss on several post on the site)
UNIX: How to add a "DIRECTORY" each line of a text file using sed? At this beginning of the line if possible? Thanks...
(Using Unix / Linux Command tool)
I have been using foreach loop and sed together, and what is now missing is just a directory each line which I am still trying to figure out... Thanks for any kind of help.
If you are looking just to add the word "DIRECTORY" then the following should be fine:
sed 's/^/DIRECTORY /' inputfile
If you are looking to add a path then I would recommend to change the delimiter.
sed 's,^,'$PWD' ,' inputfile
$ cat file.txt
one
two
three
$ cat file.txt | sed "s/one/1/"
1
two
Where is the word "three"?
UPDATED:
There is no line after the word "three".
As Ivan suggested, your text file is missing the end of line (EOL) marker on the final line. Since that's not present, three is printed out by sed but then immediately over-written by your prompt. You can see it if you force an extra line to be printed.
sed 's/one/1/' file.txt && echo
This is a common problem since people incorrectly think of the EOL as an indication that there's a following line (which is why it's commonly called a "newline") and not as an indication that the current line has ended.
Using comments from other posts:
older versions of sed do not process the last line of a file if no EOL or "new line" is present.
echo can be used to add a new line
Then, to solve the problem you can re-order the commands:
( cat file.txt && echo ) | sed 's/one/1/'
I guess there is no new line character after last line. sed didn't find line separator after last line and ignore it.
Update
I suggest you to rewrite this in perl (if you have it installed):
cat file.txt | perl -pe 's/one/1/'
Instead of cat'ing the file and piping into sed, run sed with the file name as an argument after the substitution string, like so:
sed "s/one/1/" file.txt
When I did it this way, I got the "three" immediately following by the prompt:
1
two
three$
A google search shows that the man page for some versions of sed (not the GNU or BSD versions, which work as you'd expect) indicate that it won't process an incomplete line (one that's not newline-terminated) at the end of a file. The solution is to ensure your files end with a newline, install GNU sed, or use awk or perl instead.
here's an awk solution
awk '{gsub("one","1")}1' file.txt
I have a multi line text file where each line has the format
..... Game #29832: ......
I want to append the character '1' to each number on each line (which is different on every line), does anyone know of a way to do this from the command line?
Thanks
sed -i -e 's/Game #[0-9]*/&1/' file
-i is for in-place editing, and & means whatever matched from the pattern. If you don't want to overwrite the file, omit the -i flag.
Using sed:
cat file | sed -e 's/\(Game #[0-9]*\)/\11/'
sed 's/ Game #\([0-9]*\):/ Game #1\1:/' yourfile.txt
GNU awk
awk '{b=gensub(/(Game #[0-9]+)/ ,"\\11","g",$0); print b }' file
I'm trying to do the opposite of this question, replacing Unix line endings with Windows line endings, so that I can use SQL Server bcp over samba to import the file. I have sed installed but not dos2unix. I tried reversing the examples but to no avail.
Here's the command I'm using.
sed -e 's/\n/\r\n/g' myfile
I executed this and then ran od -c myfile, expecting to see \r\n where there used to be \n. But there all still \n. (Or at least they appear to be. The output of od overflows my screen buffer, so I don't get to see the beginning of the file).
I haven't been able to figure out what I'm doing wrong. Any suggestions?
When faced with this, I use a simple perl one-liner:
perl -pi -e 's/\n/\r\n/' filename
because sed behavior varies, and I know this works.
What is the problem with getting dos2unix onto the machine?
What is the platform you are working with?
Do you have GNU sed or regular non-GNU sed?
On Solaris, /usr/bin/sed requires:
sed 's/$/^M/'
where I entered the '^M' by typing controlV controlM. The '$' matches at the end of the line, and replaces the end of line with the control-M. You can script that, too.
Mechanisms expecting sed to expand '\r' or '\\r' to control-M are going to be platform-specific, at best.
You don't need the -e option.
$ matches the endline character. This sed command will insert a \r character before the end of line:
sed 's/$/\r/' myfile
Just adding a \r (aka ^M, see Jonathan Leffler's answer) in front of \n is not safe because the file might have mixed mode EOL, so then you risk ending up with some lines becomming \r\r\n. The safe thing to do is first remove all '\r' characters, and then insert (a single) \r before \n.
#!/bin/sh
sed 's/^M//g' ${1+"$#"} | sed 's/$/^M/'
Updated to use ^M.
sed 's/\([^^M]\)$/\0^M/' your_file
This makes sure you only insert a \r when there is no \r before \n. This worked for me.
Try using:
echo " this is output" > input
sed 's/$/\r/g' input |od -c
Maybe if you try it this way
cat myfile | sed 's/\n/\r\n/g' > myfile.win
will work, from my understanding your just making the replacements to the console output, you need to redirect output to a file, in this case myfile.win, then you could just rename it to whatever you want. The whole script would be (running inside a directory full of this kind of files):
#!/bin/bash
for file in $(find . -type f -name '*')
do
cat $file | sed 's/\n/\r\n/g' > $file.new
mv -f $file.new $file
done