Sed with tab and negate match - linux

I have the following file
a
b c d e
all are tab separated.
my output should be the following
a,
b,c,d,e
i was trying following methods.
sed 's/[[:space:]]*/,/g' input.txt
this gives me the following
,a,
,b,c,d,e,
How should i remove the first comma of both lines. so the output should be like this
a,
b,c,d,e,
managed to do the following but with two sed commands.
cat input.txt | sed 's/[[:space:]]*/,/g' | sed 's/^,//' (sorry useless use of cat)
Is there a better way to do this with one sed command. (i'm not looking for awk/tr or any other method, only sed )

Add condition that there are some letters before the space:
sed 's/\([a-z]\+\)[[:space:]]*/\1,/g' input.txt
Chain two sed rules in one command (this way may be more readable):
sed 's/[[:space:]]*/,/g;s/^,//' input.txt

You could try the below sed command,
$ sed ':a;N;$!ba;s/\n/,\n/g;s/ \+/,/g' file
a,
b,c,d,e
OR
sed ':a;N;$!ba;s/\n/,\n/g;s/[[:blank:]]\+/,/g' file

Related

How to remove the multiple lines in the file using sed

The test.txt file contains 3 lines:
STREET=main
PHONE=123
EMAIL=abc#xyz.com
To remove two lines with the STREET and EMAIL I run the sed twice in a row:
sed -i -- 's/STREET=.*//' test.txt
sed -i -- 's/EMAIL=.*//' test.txt
Instead of using the sed command twice I would rather remove both lines with a single sed command. How to do it?
To delete (d) lines which contain STREET= or EMAIL=.
sed -i -- '/STREET=/d; /EMAIL=/d' file
sed -i -- 's/STREET=.*//;s/EMAIL=.*//' test.txt
The following sed one-liners show how to remove/empty the target lines:
Empty the target lines:
kent$ sed 's/^\(EMAIL\|STREET\)=.*//' file
PHONE=123
Remove the target lines:
kent$ sed '/^\(EMAIL\|STREET\)=/d' file
PHONE=123
Using pattern ^\(EMAIL\|STREET\)= will avoid to touch lines like USER_EMAIL=... or SOME_STREET=

How to replace string into numbers using sed?

I am trying to replace string into number from the file
So, I have variable &FLOW which need to change to 001, ex :
cat file.txt
This is file ' PISP &FLOW'
PISD.DATA.CYCLE&FLOW..ONE
desired output
This is file ' PISP 001'
PISD.DATA.CYCLE001.ONE
I tried below commands in a script :
for item in file.txt
do
sed 's/\&FLOW/\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
It is giving error. The second sed command is working, but I need to run first the beginning sed command otherwise after running first the second sed command, it would ignore the beginning sed command.
Any help would be appreciated!
Use a single sed command and use -i to actually modify the file contents and you need to pass file.txt as the input for the sed command:
sed -i 's/&FLOW\.\{0,1\}/001/g' file.txt
See the online demo. If you are using it in Mac OS, you need sed -i '' 's/&FLOW\.\{0,1\}/001/g' file.txt. Also see sed edit file in place.
Pattern details
It is a POSIX BRE compliant pattern matching
&FLOW - a literal &FLOW substring
\.\{0,1\} - 0 or 1 occurrence of a . char.
try this:
for item in file.txt
do
sed 's/\&FLOW\./001/g' $item
sed 's/\&FLOW/001/g' $item
done
You had a redundant / in after FLOW
This might also work:
sed -i 's/\&FLOW[\.]?/001/g' file.txt

Assistance with sed command file please

I created the following bash pipeline that will take the output of "who" and modify it to meet an assignment's requirements
This is the pipline:
who | sed -e "s/\b\(.\)/\u\1/g" | sed 's/[.]/ /g' | sed 's/ Pts\// TTY /g' | sed '1d' | sed -n 's/ .*$/ /gp'
After putting this into a sed file that looks like this:
s/\b\(.\)/\u\1/g
s/[.]/ /g
s/ Pts\// TTY /g
1d
s/ .*$/ /gp
And then running it like such:
who | sed -f sedfile
The output is correct in that everything is in the format of:
firstName lastName TTY (a number)
However each line is printed twice, where the pipeline properly printed each line once
Would anyone happen to know the issue please?
It's the gp at the last line. You're not running with sed -n (no-print), so by default you're running with sed -yesprint (or whatever). Then you hit that gp, which prints, and you get two copies.
Convert to sed -n, or change the gp to just g. Or better still, get rid of it, since the match pattern contains $, so it will only ever run in one place - the end of the line.

Delete whitespace in each begin of line of file, using bash

How i can delete whitespace in each line of file, using bash
For instance, file1.txt. Before:
gg g
gg g
t ttt
after:
gg g
gg g
t ttt
sed -i 's/ //g' your_file will do it, modifying the file inplace.
To delete only the whitespaces at the beginning of one single line, use sed -i 's/^ *//' your_file
In the first expression, we replace all spaces with nothing.
In the second one, we replace at the beginning using the ^ keyword
tr(delete all whitespaces):
$ tr -d ' ' <input.txt >output.txt
$ mv output.txt input.txt
sed(delete leading whitespaces)
$ sed -i 's/^ *//' input.txt
use can use perl -i for in place replacement.
perl -p -e 's/^ *//' file
To delete the white spaces before start of the line if the pattern matches. Use the following command.
For example your foo.in has pattern like this
This is a test
Lolll
blaahhh
This is a testtt
After issuing following command
sed -e '/This/s/ *//' < foo.in > foo.out
The foo.out will be
This is a test
Lolll
blaahhh
This is a testtt
"Whitespace" can include both spaces AND tabs. The solutions presented to date will only match and operate successfully on spaces; they will fail if the whitespace takes the form of a tab.
The below has been tested on the OP's specimen data set with both spaces AND tabs, matching successfully & operating on both:
sed 's/^[[:blank:]]*//g' yourFile
After testing, supply the -i switch to sed to make the changes persistent-

Use sed to delete all leading/following blank spaces in a text file

File1:
hello
world
How would one delete the leading/trailing blank spaces within this file using sed - using one command (no intermediate files)?
I've currently got:
sed -e 's/^[ \t]*//' a > b
For leading spaces.
sed 's/ *$//' b > c
And this for trailing spaces.
You almost got it:
sed -e 's/^[ \t]*//;s/[ \t]*$//' a > c
Moreover on some flavours of sed, there is also an option for editing inline:
sed -i -e 's/^[ \t]*//;s/[ \t]*$//' a
easier way, using awk
awk '{$1=$1}1' file
or
awk '{gsub(/^ +| +$/,"")}1' file
perl -lape 's/^\s+|\s+$//g'
Honestly, I know perl regexps the best, so I find perl -lape much easier to use than sed -e.
Also, to answer the original question, you can have sed execute multiple operations like this:
sed -e 's/something/something else/' -e 's/another substitution/another replacement/'
Apparently you can also put the two substitutions in one string and separate them with a semicolon, as indicated in another answer.
Note that in the more general case of applying several filters in a row to an input file without using intermediate files, the solution is to use pipes:
sed -e 's/^[ \t]*//' a | sed -e 's/ *$//' > c
Obviously they are not required here because one invocation of sed is sufficient, but if the second sed command was something different, like uniq or sort, then this pattern is the right one.

Resources