Write output of command to specific line - bash

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).

Related

bash one liner to remove duplicate path in line

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/
$

How to split a text file content by a string?

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 "/---/" "{*}".

Sending file contents to another command bash

I have a plain text file with two columns. I need to take each line which contains two columns and send them to a command.
The source file looks like this:
potato potato2
the line needs to be sent to another command so it looks like this
command potato potato2
output I can just have to std out.
Been such a long time that I've tried a simple bash script...
I assume that your file contains two columns per line, separated by either spaces or tabs.
xargs -n 2 command < file.txt
See: man xargs
Looks like you just need to read a file line by line, so the following code should do:
while read -r line
do
echo "$line" | xargs your-other-command #Use xargs to convert input into arguments
done < source-file.txt

How to extract (read and delete) a line from file with a single command?

I would like to extract the first line from a file, read into a variable and delete right afterwards, with a single command. I know sed can read the first line as follows:
sed '1q' file.txt
or delete it as follows:
sed '1q;d' file.txt
but can I somehow do both with a single command?
The reason for this is that multiple processes will be reading the first line of the file, and I want to minimize the chances of them getting the same line.
It's impossible.
Except you read the manpage, and have Gnu-sed:
echo -e {1..3}"\n" > input
cat input
1
2
3
sed -n '1p;2,$ Woutput' input
1
cat output
2
3
Explanation:
sed -n '1p;2,$ Woutput' input
-n no output by default
1p; print line 1
2,$ from line 2 until $ last line
W (non posix) Write buffer to file
From the man page gnu sed:
w filename
Write the current pattern space to filename.
W filename
Write the first line of the current pattern space to filename. This is a GNU extension.
However, reading and experimenting takes longer, than opening the file in a full blown office suite and deleting the line by hand, or invoking a text-to-speech framework and training it, to do the job.
It doesn't work if invoked in posix style:
sed -n --posix '1p;2,$ Woutput' input
And you still have the hard hanwork of renaming output to input again.
I didn't try to write to input in place, because that could damage my carefully crafted input file - try it on own risk:
sed -n '1p;2,$ Winput' input
However, you might set up a filesystem notify job, which always rename freshly created output files to input again. But I fear you can't do it from within the sed command. Except ... (to be continued)

Using SED to remove line from textfile

I had a look around the internet for a line of code which would delete the whole line it found a match on.. So if it found file in the file below it would delete the whole file line.. i.e '13382748 | /root/file', which it does in the console...
/root/file:
13382748 | /root/file
13382749 | /root/test
The command below works in the console (as stated above) but does not work when running the script.
sed --in-place '/$number/d' /root/file
It is the last piece to finally complete my script. The line of code simply does nothing..
Any ideas?
The single quotes prevent variable expansion. Say:
sed --in-place "/$number/d" /root/file

Resources