How do I set new line with a sed using c\? - bash

I am feeling stupid but have tried multiple ways of having new line in my script. I got help from Jonathan with a sed command. It worked great but the formatting is lost and now I can't find a way to make it work.
The code looks like this:
su -c "sed -i '/aStyle.Landscape {/,/}/c\
MImAbstractKeyAreaStyle.Landscape {\
/*** Label Setttings ***/\
label-margin-top: 10.6mm; /* 0.6 */\
label-margin-left-with-secondary: -1; /* not used, labels are centered horizontally */\
secondary-label-separation: 0;\
...
/*** Key Area Geometry ***/\
size: 854 -1;\
}' file.css"
I wanted to substitute a paragraph with another one. But with this command everything are printed on one line. I want it to keep the formatting. My original question is here: How to substitute a paragraph in file?

First try without the su -c. Between your "" quotes, the escaping is different and make it much more complicated.
When you're done, either put the result in a script file and call that with su -c ./script.sh, or adapt the escaping (but that's never gonna be nice).

This might work for you:
echo hello | sed '/.*/c\This first line is no longer "hello"\nand this is the second line\nand this the third line'
This first line is no longer "hello"
and this is the second line
and this the third line
In GNU sed you can embed the newlines \n but please see my amended answer to you last question (using a here-document) for a WYSIWYG answer.

Related

SED-POSIX-specified -E option inside script

I have a tricky question.
I have this .sed script where I need to do some stuff and then execute all the lines of the script with "sed -f script.sed filename.csv"
Inside the script I have used a regexp expression and if when executing the script I use -E, the script works. (sed -E -f script.sed filename.csv)
BUT, the thing is, I CANNOT used it, so in the terminal I need to execute the script like this "sed -f script.sed filename.csv"
Then, the question is, Is there a human possible way to make a regexp expression WORK inside a SCRIPT without using -E in the terminal? Can it be included INSIDE the SCRIPT somehow?
I will write down the script to give more context:
s/ESP/Spain/g #this line changes ESP for Spain in all rows
s/DEN/Denmark/g #this line changes DEN for Denmark in all rows
s/NED/Netherlands/g #this line changes NED for Netherlands in all rows
s/^([^,]*,)([^,]+)((,[^,]*){5},(shooting|judo),)/\1\U\2\L\3/ #This line, changes to UPPER CASE all names of athletes that have as sport either judo or shooting. This is the line that does not work without the -E in the terminal.
/[0],[0],[0],$/d #This line deletes all rows where the last 3 columns have these values
1 c id,name,nationality,sex,date_of_birth,height,weight,sport,gold,silver,bronze,info #this line makes the header not upper case
If you need some data to work with, there you have it:
id,name,nationality,sex,date_of_birth,height,weight,sport,gold,silver,bronze,info
388896171,Abdelraouf Benguit,ALG,male,1985-07-03,1.83,90,judo,0,0,0,
285603057,Abderrahmane Mansouri,ALG,male,1995-01-13,1.72,66,cycling,0,0,0,
545134894,Abderrahmane Meziane,ALG,male,1994-03-07,1.68,62,football,0,0,0,
969824503,Abdullah Alrashidi,IOA,male,1963-08-21,1.83,84,shooting,0,0,1,
897549624,Abdullah Hel Baki,BAN,male,1989-08-01,,,shooting,0,0,0,
153457,Abdullahi Shehu,NGR,male,1993-03-12,1.70,,football,0,0,1,
This is part of a file named athletesv2.csv
Please don't ask why I can't use it, but I'm forbiden from using this option.
BR,
You can use the first three commands as is:
s/ESP/Spain/g #this line changes ESP for Spain in all rows
s/DEN/Denmark/g #this line changes DEN for Denmark in all rows
s/NED/Netherlands/g #this line changes NED for Netherlands in all rows
The fourth command should be "converted" to POSIX BRE:
s/^\([^,]*,\)\([^,]\+\)\(\(,[^,]*\)\{5\},\(shooting\|judo\),\)/\1\U\2\L\3/
Note that this syntax is only supported by GNU sed (the \| as an alternation operator and \+ as one or more quantifier are GNU extensions).

Understanding 'sed' command

I am currently trying to install GCC-4.1.2 on my machine: Fedora 20.
In the instruction, the first three commands involve using 'sed' commands, for Makefile modification. However, I am having difficulty in using those commands properly for my case. The website link for GCC-4.1.2.
The commands are:
sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in &&
sed -i 's#\./fixinc\.sh#-c true#' gcc/Makefile.in &&
sed -i 's/#have_mktemp_command#/yes/' gcc/gccbug.in &&
I am trying to understand them by reading the 'sed' man page, but it is not so easy to do so. Any help/tip would be appreciated!
First, the shell part: &&. That just chains the commands together, so each subsequent line will only be run if the prior one is run successfully.
sed -i means "run these commands inline on the file", that is, modify the file directly instead of printing the changed contents to STDOUT. Each sed command here (the string) is a substitute command, which we can tell because the command starts with s.
Substitute looks for a piece of text in the file, and then replaces it. So the order is always s/needle/replacement/. See how the first and last lines have those same forward-slashes? That's the traditional delimiter between the command (substitute), the needle to find in the haystack (install_to_$(INSTALL_DEST), and the text to replace it with ().
So, the first one looks for the string and deletes it (the empty replacement). The last one looks for #have_mktemp_command# and replaces it with yes.
The middle one is a bit weird. See how it starts with s# instead of s/? Well, sed will let you use any delimiter you like to separate the needle from the replacement. Since this needle had a / in it (\./fixinc\.sh), it made sense to use a different delimiter than /. It will replace the text ./fixinc.sh with -c true.
Last note: Why does the second needle have \. instead of .? Well, in a Regular Expression like the needle is (but not used in your example), some characters are magical and do magical fairy dust operations. One of those magic characters is .. To avoid the magic, we put a \ in front of it, escaping away from the magic. (The magic is "match any character", and we want a literal period. That's why.)

use sed with for loop to delete lines from text file

I am essentially trying to use sed to remove a few lines within a text document. To clean it up. But I'm not getting it right at all. Missing something and I have no idea what...
#!/bin/bash
items[0]='X-Received:'
items[1]='Path:'
items[2]='NNTP-Posting-Date:'
items[3]='Organization:'
items[4]='MIME-Version:'
items[5]='References:'
items[6]='In-Reply-To:'
items[7]='Message-ID:'
items[8]='Lines:'
items[9]='X-Trace:'
items[10]='X-Complaints-To:'
items[11]='X-DMCA-Complaints-To:'
items[12]='X-Abuse-and-DMCA-Info:'
items[13]='X-Postfilter:'
items[14]='Bytes:'
items[15]='X-Original-Bytes:'
items[16]='Content-Type:'
items[17]='Content-Transfer-Encoding:'
items[18]='Xref:'
for f in "${items[#]}"; do
sed '/${f}/d' "$1"
done
What I am thinking, incorrectly it seems, is that I can setup a for loop to check each item in the array that I want removed from the text file. But it's simply not working. Any idea. Sure this is basic and simple and yet I can't figure it out.
Thanks,
Marek
Much better to create a single sed script, rather than generate 19 small scripts in sequence.
Fortunately, generating a script by joining the array elements is moderately easy in Bash:
regex=$(printf '\|%s' "${items[#]}")
regex=${regex#'\|'}
sed "/^$regex/d" "$1"
(Notice also the addition of ^ to the final regex -- I assume you only want to match at beginning of line.)
Properly, you should not delete any lines from the message body, so the script should leave anything after the first empty line alone:
sed "1,/^\$/!b;/$regex/d" "$1"
Add -i if you want in-place editing of the target file.

Removing two consecutive line breaks

My file has a lot of line breaks, like this:
This is a line.
This is another line.
I would like to remove these, but only in cases where the first line ends with }, e.g.:
\macro{This is a line.}
This is another line.
That should become:
\macro{This is a line.}This is another line.
How can I remove the line breaks in this situation?
This is what I figured out:
$ sed -n '/}$/{h;:a;n;/^$\|}$/{H;$!ba};H;g;s#}\n*#}#g};p' input.txt
The idea behind is:
Accumulate all continuous empty lines and lines endswith '}'
Substitute }\n* with }
Last line needs special consideration.
You can just use an editor that support regular expressions and do a replace in your file. Replace:
}$\n\n
with
}
If you need to do it programmatically, the same principle applies (i.e. using regex for string replacement) but the actual answer will obviously depend on language/environment.
This might work for you:
sed '$!N;s/}\n$/}/;P;D' file
if there is white space involved, try:
sed '$!N;s/}\s*\n\s*$/}/;P;D' file
or more formally:
sed '$!N;s/}[[:space:]]*\n[[:space:]]*$/}/;P;D' file

bash templating

i have a template, with a var LINK
and a data file, links.txt, with one url per line
how in bash i can substitute LINK with the content of links.txt?
if i do
#!/bin/bash
LINKS=$(cat links.txt)
sed "s/LINKS/$LINK/g" template.xml
two problem:
$LINKS has the content of links.txt without newline
sed: 1: "s/LINKS/http://test ...": bad flag in substitute command: '/'
sed is not escaping the // in the links.txt file
thanks
Use some better language instead. I'd write a solution for bash + awk... but that's simply too much effort to go into. (See http://www.gnu.org/manual/gawk/gawk.html#Getline_002fVariable_002fFile if you really want to do that)
Just use any language where you don't have to mix control and content text. For example in python:
#!/usr/bin/env python
links = open('links.txt').read()
template = open('template.xml').read()
print template.replace('LINKS', links)
Watch out if you're trying to force sed solution with some other separator - you'll get into the same problems unless you find something disallowed in urls (but are you verifying that?) If you don't, you already have another problem - links can contain < and > and break your xml.
You can do this using ed:
ed template.xml <<EOF
/LINKS/d
.r links.txt
w output.txt
EOF
The first command will go to the line
containing LINKS and delete it.
The second line will insert the
contents of links.txt on the current
line.
The third command will write the file
to output.txt (if you omit output.txt
the edits will be saved to
template.xml).
Try running sed twice. On the first run, replace / with \/. The second run will be the same as what you currently have.
The character following the 's' in the sed command ends up the separator, so you'll want to use a character that is not present in the value of $LINK. For example, you could try a comma:
sed "s,LINKS,${LINK}\n,g" template.xml
Note that I also added a \n to add an additional newline.
Another option is to escape the forward slashes in $LINK, possibly using sed. If you don't have guarantees about the characters in $LINK, this may be safer.

Resources