Add a specific word to end of line - sed

I want to add specific word in end of the line in my file.
My file is mac.txt containing,
00-1E-B8-05-7C-74
I want to add :p=abcde to the end.
I tried:
cat mac.txt | sed '$/:p=1234' > mac2.txt
cat mac.txt | sed -e 's/$/:p=1234/' > mac2.txt
sed 's/$/:p=1234/' mac.txt > newmac.txt
sed 's/\(.*\)/\1:p=1234/' < mac.txt > outfile.txt
but what they are doing is adding text to next line like
00-1E-B8-05-7C-74
:p=abcde
I want my output to be:
00-1E-B8-05-7C-74:p=abcde

With awk you can do this:
awk '/00-1E-B8-05-7C-74/ {$0=$0":p=abcde"} 1' file
00-1E-B8-05-7C-74:p=abcde
It will add :p=abcde after lines with 00-1E-B8-05-7C-74
Update:
awk '$0~m {$0=$0":p=abcde"} 1' m=$(cat mac.txt) file

The first command should fail since that is not a valid sed expression.
The second command should work.
The third command should work.
The fourth command is overkill but should work too.
Demonstration:
$ cat mac.txt
00-1E-B8-05-7C-74
$ cat mac.txt | sed '$/:p=1234' > mac2.txt
sed: 1: "$/:p=1234": invalid command code /
$ cat mac.txt | sed -e 's/$/:p=1234/' > mac2.txt
$ cat mac2.txt
00-1E-B8-05-7C-74:p=1234
$ sed 's/$/:p=1234/' mac.txt > newmac.txt
$ cat newmac.txt
00-1E-B8-05-7C-74:p=1234
$ sed 's/\(.*\)/\1:p=1234/' < mac.txt > outfile.txt
$ cat outfile.txt
00-1E-B8-05-7C-74:p=1234
$

Related

Wrap each line in a text file in apostrophes and add comma to end of lines

My actual text document contains the following lines.
san.20140226.sbc.UTM
san.201402261.UTM
san.2014022613.UTM
I want the below output:
'san.20140226.sbc.UTM',
'san.201402261.UTM',
'san.2014022613.UTM',
You could try this sed command,
sed "s/.*/'&',/g" file
Example:
$ echo 'san.20140226.sbc.UTM' | sed "s/.*/'&',/g"
'san.20140226.sbc.UTM',
OR
$ echo 'san.20140226.sbc.UTM' | sed "s/^/'/;s/$/',/"
'san.20140226.sbc.UTM',
^ matches the start of a line and $ matches the end of a line.

sed script to remove everything in brackets over multiple lines

I am trying to use sed script to remove the content of an array in a file. I have tried to delete the content to only leave the brackets (). However I can't get the sed script to work over multiple lines.
I am trying to change the current state of the file:
LIST = ( "content"
"content1"
"content3")
to this:
LIST = ()
However the sed script I am using only changes the file to this:
LIST = ()
"content"
"content1"
"content2"
sed -e 's/LIST=\([^)]*\)/LIST=() /g' filename
I should also mention there are other sets of brackets in the file which I don't want affected.
e.g
LISTNUMBER2("CONTENT")
should not be emptied.
this sed one-liner works for your example:
sed -n '1!H;1h;${x;s/(.*)/()/;p}'
test:
kent$ echo 'LIST = ( "content"
"content1"
"content3")'|sed -n '1!H;1h;${x;s/(.*)/()/;p}'
LIST = ()
if you could use awk, this one-liner works for your example too:
awk -v RS="" '{sub(/\(.*\)/,"()")}1'
test:
kent$ echo 'LIST = ( "content"
"content1"
"content3")'|awk -v RS="" '{sub(/\(.*\)/,"()")}1'
LIST = ()
EDIT for OP's comment
multi brackets situation:
awk
awk -v RS="\0" -v ORS="" '{gsub(/LIST\s*=\s*\([^)]*\)/,"LIST = ()")}1' file
test:
kent$ cat file
LISTKEEP2("CONTENT")
LIST = ( "content"
"content1"
"content3")
LISTNUMBER2("CONTENT")
kent$ awk -v RS="\0" -v ORS="" '{gsub(/LIST\s*=\s*\([^)]*\)/,"LIST = ()")}1' file
LISTKEEP2("CONTENT")
LIST = ()
LISTNUMBER2("CONTENT")
sed:
sed -nr '1!H;1h;${x;s/(LIST\s*=\s*\()[^)]*\)/\1)/;p}' file
kent$ sed -nr '1!H;1h;${x;s/(LIST\s*=\s*\()[^)]*\)/\1)/;p}' file
LISTKEEP2("CONTENT")
LIST = ()
LISTNUMBER2("CONTENT")
Another sed solution:
sed '/LIST = (/{:next;/)/{s/(.*)/()/;b;};N;b next;}'
Here's a version that would not change any block containing a certain string ("keepme" in this example, but could be anything):
sed '/LIST = (/{:next;/)/{/keepme/b;s/(.*)/()/;b;};N;b next;}'
Since this does the keepme test after it finds the closing parenthesis that tag can be anywhere in the block.

Exclude e-mails which domain name match with the global one

The global domain are in "*#" option, when e-mail match with one of these global domains, I need to exclude them from the list.
Example:
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#superuser.com
WF,test#stackapps.com
WF,test#stackexchange.com
Output:
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
You have two types of data in the same file, so the easiest way to process is to divide it first:
<infile tee >(grep '\*#' > global) >(grep -v '\*#' > addr) > /dev/null
Then use global to remove information from addr:
grep -vf <(cut -d# -f2 global) addr
Putting it together:
<infile tee >(grep '\*#' > global) >(grep -v '\*#' > addr) > /dev/null
cat global <(grep -vf <(cut -d# -f2 global) addr) > outfile
Contents of outfile:
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
Clean up temporary files with rm global addr.
$ awk -F, 'NR==FNR && /\*#/{a[substr($2,3)]=1;print;next}NR!=FNR && $2 !~ /^\*/{x=$2;sub(/.*#/,"",x); if (!(x in a))print;}' OFS=, file file
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
You could do:
grep -o "\*#.*" file.txt | sed -e 's/^/[^*]/' > global.txt
grep -vf global.txt file.txt
This will start by extracting the global emails, and prepend them with [^*], saving the results into global.txt. This file is then used as input to grep, where each line is treated as a regex in the form [^*]*#global.domain.com. The -v option tells grep to only print lines that don't match that pattern.
Another analogous option, using sed for in-place editing would be:
grep -o "\*#.*" file.txt | sed -e 's/^.*$/\/[^*]&\/d/' > global.sed
sed -i -f global.sed file.txt
Here's one way using GNU awk. Run like:
awk -f script.awk file.txt{,}
Contents of script.awk:
BEGIN {
FS=","
}
FNR==NR {
if (substr($NF,1,1) == "*") {
array[substr($NF,2)]++
}
next
}
substr($NF,1,1) == "*" || !(substr($NF,index($NF,"#")) in array)
Results:
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
Alternatively, here's the one-liner:
awk -F, 'FNR==NR { if (substr($NF,1,1) == "*") array[substr($NF,2)]++; next } substr($NF,1,1) == "*" || !(substr($NF,index($NF,"#")) in array)' file.txt{,}
This might work for you (GNU sed):
sed '/.*\*\(#.*\)/!d;s||/[^*]\1/d|' file | sed -f - file
With one pass of the file and allowing for the global domains to be intermixed with the addresses:
$ cat file
WF,*#stackoverflow.com
WF,test#superuser.com
WF,*#superuser.com
WF,test#stackapps.com
WF,test#stackexchange.com
WF,*#stackexchange.com
WF,foo#stackapps.com
$
$ awk -F'[,#]' '
$2=="*" { glbl[$3]; print; next }
{ addrs[$3] = addrs[$3] $0 ORS }
END {
for (dom in addrs)
if (!(dom in glbl))
printf "%s",addrs[dom]
}
' file
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
WF,foo#stackapps.com
or if you don't mind a 2-pass approach:
$ awk -F'[,#]' '(NR==FNR && $2=="*" && !glbl[$3]++) || (NR!=FNR && !($3 in glbl))' file file
WF,*#stackoverflow.com
WF,*#superuser.com
WF,*#stackexchange.com
WF,test#stackapps.com
WF,foo#stackapps.com
I know that second one's a bit cryptic, but it's pretty easily translated to not use the default action and a good exercise in awk idioms :-).

Unix - Removing everything after a pattern using sed

I have a file which looks like below:
memory=500G
brand=HP
color=black
battery=5 hours
For every line, I want to remove everything after = and also the =.
Eventually, I want to get something like:
memory:brand:color:battery:
(All on one line with colons after every word)
Is there a one-line sed command that I can use?
sed -e ':a;N;$!ba;s/=.\+\n\?/:/mg' /my/file
Adapted from this fine answer.
To be frank, however, I'd find something like this more readable:
cut -d = -f 1 /my/file | tr \\n :
Here's one way using GNU awk:
awk -F= '{ printf "%s:", $1 } END { printf "\n" }' file.txt
Result:
memory:brand:color:battery:
If you don't want a colon after the last word, you can use GNU sed like this:
sed -n 's/=.*//; H; $ { g; s/\n//; s/\n/:/g; p }' file.txt
Result:
memory:brand:color:battery
This might work for you (GNU sed):
sed -i ':a;$!N;s/=[^\n]*\n\?/:/;ta' file
perl -F= -ane '{print $F[0].":"}' your_file
tested below:
> cat temp
abc=def,100,200,dasdas
dasd=dsfsf,2312,123,
adasa=sdffs,1312,1231212,adsdasdasd
qeweqw=das,13123,13,asdadasds
dsadsaa=asdd,12312,123
> perl -F= -ane '{print $F[0].":"}' temp
abc:dasd:adasa:qeweqw:dsadsaa:
My command is
First step:
sed 's/([a-z]+)(\=.*)/\1:/g' Filename |cat >a
cat a
memory:
brand:
color:
battery:
Second step:
sed -e 'N;s/\n//' a | sed -e 'N;s/\n//'
My output is
memory:brand:color:battery:

How can I add the current date or time to end of each line in file?

I have a file called data.txt.
I want to add the current date, or time, or both to the beginning or end of each line.
I have tried this:
awk -v v1=$var ' { printf("%s,%s\n", $0, v1) } ' data.txt > data.txt
I have tried this:
sed "s/$/,$var/" data.txt
Nothing works.
Can someone help me out here?
How about :
cat filename | sed "s/$/ `date`/"
The problem with this
awk -v v1=$var ' { printf("%s,%s\n", $0, v1) } ' data.txt > data.txt
is that the > redirection happens first, and the shell truncates the file. Only then does the shell exec awk, which then reads an empty file.
Choose one of these:
sed -i "s/\$/ $var/" data.txt
awk -v "date=$var" '{print $0, date}' data.txt > tmpfile && mv tmpfile data.txt
However, does your $var contain slashes (such as "10/04/2011 12:34") ? If yes, then choose a different delimiter for sed's s/// command: sed -i "s#\$# $var#" data.txt