Sed print nextline and change it - sed

My file:
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"$t":"randomtext"}]}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"$t":"randomtext222"}]}
"title":{"type":"text"
"$t":"randomtext"}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"$t":"randomtext"}]}
I need to change $t on the line after postalAddress but not $t after the line with title.
This will print the lines i want to change.
sed -n '/postalAddress/ {n;p}' file.txt
This will print the line i want to change, with the change included:
sed -n '/postalAddress/ {n;p}' file.txt | sed 's/"$t":"/CHANGE/'
But how do i change this in my file ?
Here's how my file should look like:
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext222"}]}
"title":{"type":"text"
"$t":"randomtext"}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}

Using sed
sed '/postalAddress/{n;s/\$t/CHANGE/;}' file
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext222"}]}
"title":{"type":"text"
"$t":"randomtext"}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}
With awk you can do:
awk '/postalAddress/ {print;getline;sub(/\$t/,"CHANGE")}1' file
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext222"}]}
"title":{"type":"text"
"$t":"randomtext"}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
"CHANGE":"randomtext"}]}
Using flag with awk:
awk '/postalAddress/ {f=NR+1} f==NR {sub(/\$t/,"CHANGE");f=0}1 file

You really ought to do this using a language that understands your data, which appears to be JSON, so perhaps Python. But we can do it using sed:
sed '/}]}/ s/"$t":"/CHANGE/' file.txt
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
CHANGErandomtext"}]}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
CHANGErandomtext222"}]}
"title":{"type":"text"
"$t":"randomtext"}
"gd$postalAddress":[{"rel":"http://schemas.google.com/g/2005#home"
CHANGErandomtext"}]}
This relies on the punctuation being the way it is on the end of the lines you care about, and not on the ones you don't.

Related

Replace a directory string with a ".." using sed

How can I do these in sed?
#input #output
file.txt "nothing"
dir1/ ../
dir1/file.txt ../
dir1/dir2/ ../../
dir1/dir2/file.txt ../../
Let's say #input is placed to $var1
sed "do something" <<< $var1
echo $var1
You can try this GNU sed
sed "s#dir[0-9]\+/*#\.\./#g; s#file\.txt##g"
Is your test for dir1/dir2 (without trailing slash) correct? How does sed know if dir2 is a file or a directory? Otherwise you could use:
echo "dir1/dir2/file.txt" | sed s#[^/]*/#../#g | sed 's#[^/]*$##'

Removing matching text from line

I have a example cut down from a log file.
112 172.172.172.1#50912 (ssl.bing.com):
I would like some how to remove the # and numbers after and (): from the url.
Would like the result.
112 172.172.172.1 ssl.bing.com
Here is the sed oneliner I have been working on.
cat newdns.log | sed -e 's/.*query: //' | cut -f 1 -d' ' | sort | uniq -c | sort -k2 > old.log
Thanks
Using sed, you could say:
sed 's/#[0-9]*//;s/(\(.*\)):$/\1/' filename
or, in a single substitution:
sed 's/#[0-9]* *(\(.*\)):$/ \1/' filename
Another sed:
sed -r 's/#[^ ]+|[():]//g'
$ echo '112 172.172.172.1#50912 (ssl.bing.com):' | sed -r 's/#[^ ]+|[():]//g'
112 172.172.172.1 ssl.bing.com

Substituting path

I want to replace path in
(setq myFile "/some/path")
in a file. I tried to do it with sed:
find ./_build/html -type f -name '*.html' | while read myFile; do
MyFile=`readlink -f "$myFile"`
sed -i "s/setq myFile [)]*/setq myFile \"$MyFile\"/" sphinx_nowrap.el
# and then some actions on file
done
and with perl:
find ./_build/html -type f -name '*.html' | while read myFile; do
MyFile=`readlink -f "$myFile"`
perl -ne "s/setq myFile .+/setq myFile \"$MyFile\")/" sphinx_nowrap.el
# and then some actions on file
done
but both give errors.
I've read this and this and also this -- but can't make it work.
Edit:
Here's a perl error:
Having no space between pattern and following word is deprecated at -e line 1.
Bareword found where operator expected at -e line 1, near "s/setq myFile .+/setq myFile "/home"
String found where operator expected at -e line 1, at end of line
(Missing semicolon on previous line?)
syntax error at -e line 1, near "s/setq myFile .+/setq myFile "/home"
Can't find string terminator '"' anywhere before EOF at -e line 1.
and here's sed error:
sed: -e expression #1, char 34: unknown option to `s'
Edit 2:
So the solution is to change the delimeter char. And also sed expression should be changed:
sed -i "s!setq myFile .*!setq myFile \"$MyFile\")!" sphinx_nowrap.el
Looks like perl (and sed) recognizes the slash in the file path as the regex delimiter. You can use a different delimiter:
find ./_build/html -type f -name '*.html' | while read myFile; do
MyFile=`readlink -f "$myFile"`
perl -ne "s!setq myFile .+!setq myFile \"$MyFile\")!" sphinx_nowrap.el
# and then some actions on file
done
or for sed:
find ./_build/html -type f -name '*.html' | while read myFile; do
MyFile=`readlink -f "$myFile"`
sed -i "s!setq myFile [)]*!setq myFile \"$MyFile\"!" sphinx_nowrap.el
# and then some actions on file
done
Lets assume your $MyPath hold /foo/bar/baz. Then the Perl code reads as:
perl -ne "s/setq myFile .+/setq myFile \"/foo/bar/baz\")/" sphinx_nowrap.el
Your Regex is terminated with the third / character. To work around this, we can use another delimiter like s{}{}:
perl -ine "s{setq myFile .+}{setq myFile \"/foo/bar/baz\")}; print" sphinx_nowrap.el
I also added the -i Option (inplace editing) and a print statement so that something actually gets print out.
But probably it would be more elegant to pass the value aof $MyPath as a command line argument:
perl -ne 's{setq myFile .+}{setq myFile "$ARGV[0]")}; print' $MyPath <sphinx_nowrap.el >sphinx_nowrap.el

sed character replacement in portion of a line

New to sed and could use some help.
I would like to turn this "a/b/c a/b/c" into this "a/b/c a-b-c".
where a/b/c is any path.
thanks
Give this a try:
sed 'h; s/ .*//; x; s/.* //; s:/:-:g; x; G; s/\n/ /'
Since you want to use whitespace to delemit, I'd just use perl:
perl -ane '$F[1] =~ s/\//-/; print "#F\n"'
you can use awk,
$ echo "a/b/c a/b/c" | awk '{gsub("/","-",$NF)}1'
a/b/c a-b-c
This might work:
echo "a/b/c a/b/c" | sed ':a;s|\(.* [^/]*\)/|\1-|;ta'
a/b/c a-b-c
Or this:
echo "a/b/c a/b/c" | sed 's/.* //;h;y/\//-/;x;G;y/\n/ /'
a/b/c a-b-c

Convert stdin to one file per line

I would like to write a small script using the standard linux shell scripting tools (sed, awk, etc.) to create one output file per line of input. For example, given the following input file 'input':
line1
line2
line3
I would like to run the command.
$ cat input | my_prog
Where 'my_prog' is a script that creates three output files, out.1, out.2, out.3
$ cat out.1
line1
$ cat out.2
line2
$ cat out.3
line3
count=0
for line in $(cat input)
do
echo $line > out.$count
let count=count+1
done
perl -ne 'open my $fh, ">out.$." && print $fh $_' input.txt
using awk
awk '{print $0 > "out_"++d".txt"}' file
#!/bin/bash
while IFS= read -r line; do
echo "$line" > out.$((++i))
done < /path/to/input