I have a file with lot of a strings and one line starts with LIBXML2_INCLUDE
and the file is generated by another program to be specific by ./configure, this line wrongly gives two path and the first path is not correct and i need to remove it. This is how the line appears in file
LIBXML2_INCLUDE=-I/home/gan/Music/wvm/build/level/ast/deliveryx/libxml2//home/gan/Music/wvm/build/level/ast/deliveryx/libxml2/include/libxml2
i need to remove first /home/gan/Music/wvm/build/level/ast/deliveryx/libxml2/
and expected output is
LIBXML2_INCLUDE=-I/home/gan/Music/wvm/build/level/ast/deliveryx/libxml2/include/libxml2
How can i create a bash one liner to accomplish this?
Try like this:
# cat file
SOMEVAR=-I/some/path//some/path
# sed -i -e '/^SOMEVAR=/s,=-I.*//,=-I/,' file
# cat file
SOMEVAR=-I/some/path
#
To be a bit more fancy --
$ cat file
SOMEVAR=-I/some/path//some/path
$ sed -i -e '/^SOMEVAR=/s,=-I\(.*\)/\1$,=-I\1/,' file
$ cat file
SOMEVAR=-I/some/path/
$
Related
Suppose I've got a text file that consists of two parts separated by delimiting string ---
aa
bbb
---
cccc
dd
I am writing a bash script to read the file and assign the first part to var part1 and the second part to var part2:
part1= ... # should be aa\nbbb
part2= ... # should be cccc\ndd
How would you suggest write this in bash ?
You can use awk:
foo="$(awk 'NR==1' RS='---\n' ORS='' file.txt)"
bar="$(awk 'NR==2' RS='---\n' ORS='' file.txt)"
This would read the file twice, but handling text files in the shell, i.e. storing their content in variables should generally be limited to small files. Given that your file is small, this shouldn't be a problem.
Note: Depending on your actual task, you may be able to just use awk for the whole thing. Then you don't need to store the content in shell variables, and read the file twice.
A solution using sed:
foo=$(sed '/^---$/q;p' -n file.txt)
bar=$(sed '1,/^---$/b;p' -n file.txt)
The -n command line option tells sed to not print the input lines as it processes them (by default it prints them). sed runs a script for each input line it processes.
The first sed script
/^---$/q;p
contains two commands (separated by ;):
/^---$/q - quit when you reach the line matching the regex ^---$ (a line that contains exactly three dashes);
p - print the current line.
The second sed script
1,/^---$/b;p
contains two commands:
1,/^---$/b - starting with line 1 until the first line matching the regex ^---$ (a line that contains only ---), branch to the end of the script (i.e. skip the second command);
p - print the current line;
Using csplit:
csplit --elide-empty-files --quiet --prefix=foo_bar file.txt "/---/" "{*}" && sed -i '/---/d' foo_bar*
If version of coreutils >= 8.22, --suppress-matched option can be used and sed processing is not required, like
csplit --suppress-matched --elide-empty-files --quiet --prefix=foo_bar file.txt "/---/" "{*}".
I have four files named source, correct, wrong and not_found. I am trying to write a script in bash wherein I read each line from file named source, store the line as variable x, and match it against a condition.
If it passes, then I need to write that line to file named correct, but the catch is before writing into correct I need to check if the variable x is currently present in file named wrong and if yes delete it and then add the line to file named correct.
I have tried below, but it doesn't modify the file and neither gives me any output:
sed -i '/$x/d' ./wrong
As you have already understood, variables inside '...' are not expanded.
If you replace the single-quotes with double-quotes,
this will delete the matching line from ./wrong:
sed -i "/$x/d" ./wrong
But you also want to add the line to ./correct, if there was a match.
To do that, you can run grep before the sed:
grep "$x" ./wrong >> ./correct
This will have the desired effect,
but sed will overwrite ./wrong, even when it doesn't need to.
You can prevent that like this:
if grep "$x" ./wrong >> ./correct; then
sed -i "/$x/d" ./wrong
fi
I am trying to remove the last newline added to the file using bash script.
I have got this -
truncate -s $(($(stat -c '%s' foo.txt)-1)) foo.txt
here foo.txt the file name.
but I want to parametrize the file name, I will pas the file name to the script and it should this remove the newline at last from that file.
Request your help on this. I do not have linux in my machine and tried using cygwin but it is giving error while running the script.
Thanks
To remove last line if it is newline use this sedL
sed -i.bak '/^[[:blank:]]*$/{$d;}' foo.txt
I need to write the output of a command to a specific line in a document. I can not just append it like so COMMAND | cat >> file, I need it to be added between two lines without replacing one or the other. I'm sure you must be able to do this via sed.
The following solution works when the output of COMMAND is only 1 line (inserting to line 4):
COMMAND | sed -i "4i \`cat` FILE"
Use that command:
command | sed -i '3r /dev/stdin' file
That inserts text after the 3rd line and reads from stdin (all output from command).
#!/bin/sed -f
s/","/|/g; # global change of "," to bar
# do some more stuff
#s/|/","/g; # global change of bar back to ","
#---end of script---
The above script removes the 2nd field from a CSV, and clears out quotes and such. I didn't include most of the script because it's not pertinent to the question.
The script is saved in the file fix.sh.
I can run it on a file like this:
$ ./fix.sh <myfile.txt >outputfile.txt
And it works great.
But I want it to replace in file. This doesn't work:
$ ./fix.sh <myfile.txt >myfile.txt
It results in an empty myfile.txt.
This doesn't work either:
$ ./fix.sh myfile.txt
I tried finding some documentation on sed bash scripts but didn't find anything to help me.
I'm sure the answer is simple, I just can't find it. Thanks for your help.
EDIT: I should have mentioned that this is running on a CentOS 6 machine.
Full script is below. Its overall result is to remove field#2 and strip quotes.
#!/bin/sed -nf
# adapted from http://www.linuxtopia.org/online_books/linux_tool_guides/the_sed_faq/sedfaq4_005.html
s/","/|/g; # global change of "," to bar
s/^"//;
s/"$//;
s/^\([^|]*\)|[^|]*|/\1|/; # delete 2nd field contents
s/||/|/; # change || to |
s/ //g; # remove spaces
s/|/,/g;
#s/|/","/g; # global change of bar back to ","
#---end of script---
If your sed supports -i option then you can run your script like this:
./fix.sh -i myfile.txt
-i option of sed does the in-file substitutions.
If your version of sed does not support the -i option then you can do the following which is pretty much the same thing that -i does behind the scene:
./fix.sh myfile.txt > temp && mv temp myfile.txt
Why redirecting to the same file doesn't work?
The reason is that the redirection opens the file for writing and ends up clearing any existing contents. sed then tries to read this empty file, and does nothing. The file is then closed and there by you get an empty file.