Search word starting with '-', if next word does not start with same pattern then keep it in same line, else move it to new line - sed

I have a text file which contains bunch of strings as shown below.
-V -am line+tgl -am assert -debug+all -zdb -fcs_assert off
I want to search for string starting with pattern '-' and check if the next word starts with '-'. If it does then move it to next line, else keep it in the same line.
Expected output:
-V
-am sqr+tgl
-am assert
-debug+all
-zdb
-fcs_assert off
I tried replacing space with next line character and lines which don't start with '-' append it to previous line. I am unable to figure out the second half of this approach.
cat ins.tmp/cmd.vcs | sed 's/ /\n/g'

Replace a space followed by a dash by a newline followed by a dash.
sed 's/ -/\n-/g' file

You may use this awk solution:
awk -F ' +-' -v OFS='\n-' '{$1=$1} 1' file
-V
-am line+tgl
-am assert
-debug+all
-zdb
-fcs_assert off

Another option specifying the row separator RS to one or more spaces followed by -
Prepend a hyphen starting from the second row on, so that there has been at least one match for the row separator.
awk -v RS=" +-" '{print (NR==1 ? $0 : "-"$0)}' file
Output
-V
-am line+tgl
-am assert
-debug+all
-zdb
-fcs_assert off

Related

How to edit beginning and ending of file with sed

I'm trying to add array brackets at the beginning and end of a file using sed (after first removing the trailing comma at the end of the file) to put all the content of the file in an array. I'm first using this sed command to remove the last comma from a file
sed '$ s/,$//' "$path"
After that, I'm using the middle command below to add array brackets at beginning and ending of file
sed '$ s/,$//' "$path" | sed 's/^.*$/[&]/' | tee $filename
This sed 's/^.*$/[&]/' was supposed to match everything (from beginning to end ^$) and then put brackets around the whole match [&] (i.e. as if to make it into an array), but it instead put array brackets around the beginning and end of each line.
Question, how to edit the beginning and ending of a file with sed?
whole script
for path in dirname/* do
name="${path##*/}"
sed '$ s/,$//' "$path" | sed 's/^.*$/[&]/' | tee "newdir/$name"
done
sed is an editor that works line by line, so the command sed 's/^.*$/[&]/' would add brackets to every line. If you want to edit just the beginning and end of a file you need to put line numbers in front of the substitutions ($ stands for the last line):
sed -e '1 s/^/[/' -e '$ s/$/]/'
Since you already have a command that removes trailing ,'s you could combine it with the aforementioned substitutions. Your command line would then look like this:
sed -e '1 s/^/[/' -e '$ s/,*$/]/' "$path" | tee $filename

Grep and replace the character from grepped result

I am trying to grep the line from file and then from $1 I am trying to change the character.
eg
cat file1.txt
Surjit
Shilpa
cchiku
end of file
I tried and grepped the line which start with s.
grep -e "S"
Then I want to replace the 4th character to x for all grepped result in the file1.txt
I tried
sed -i "s/./x/4" file1.txt
How can I do this only for grepped results?
You can use the sed '/pattern/s/find/replace/' file syntax:
sed '/^S/s/./x/4' file
# ^^ ^^^^^^^
# | replace the 4th character with x
# |
# on lines starting with S
With your file:
$ sed '/^S/s/./x/4' file
Surxit
Shixpa
cchiku
end of file
Note I am using /^S/ as a pattern to match lines starting with S, because if you just say /S/ it will match any line containing S. The anchor ^ indicates the beginning of the line.
An alternative to fedorqui's answer is to include the starting with S condition into the pattern itself:
sed 's/^\(S..\)./\1x/' file
The command matches lines starting with S and puts the S and the following two characters into a matching group. In the replacement part the content of the matching group will get reused and next character after it will get replaced by x.
awk -v FS="" -v OFS="" '/^S/{$4="x"}1' infile
Surxit
Shixpa
cchiku
end of file

UNIX Replacing a character sequence in either tr or sed

Have a file that has been created incorrectly. There are several space delimited fields in the file but one text field has some unwanted newlines. This is causing a big problem.
How can I remove these characters but not the wanted line ends?
file is:
'Number field' 'Text field' 'Number field'
1 Some text 999999
2 more
text 111111111
3 Even more text 8888888888
EOF
So there is a NL after the word "more".
I've tried sed:
sed 's/.$//g' test.txt > test.out
and
sed 's/\n//g' test.txt > test.out
But none of these work. The newlines do not get removed.
tr -d '\n' does too much - I need to remove ONLY the newlines that are preceded by a space.
How can I delete newlines that follow a space?
SunOS 5.10 Generic_144488-09 sun4u sparc SUNW,Sun-Fire-V440
A sed solution is
sed '/ $/{N;s/\n//}'
Explanation:
/ $/: whenever the line ends in space, then
N: append a newline and the next line of input, and
s/\n//: delete the newline.
It might be simplest with Perl:
perl -p0 -e 's/ \n/ /g'
The -0 flag makes Perl read the entire file as one line. Then we can substitute using s in the usual way. You can, of course, also add the -i option to edit the file in-place.
How can I delete newlines that follow a space?
If you want every occurrence of $' \n' in the original file to be replaced by a space ($' '), and if you know of a character (e.g. a control character) that does not appear in the file, then the task can be accomplished quite simply using sed and tr (as you requested). Let's suppose, for example, that control-A is a character that is not in the file. For the sake of simplicity, let's also assume we can use bash. Then the following script should do the job:
#!/bin/bash
A=$'\01'
tr '\n' "$A" | sed "s/ $A/ /g" | tr "$A" '\n'

Using sed to keep the beginning of a line

I have a file in which some lines start by a >
For these lines, and only these ones, I want to keep the first eleven characters.
How can I do that using sed ?
Or maybe something else is better ?
Thanks !
Muriel
Let's start with this test file:
$ cat file
line one with something or other
>1234567890abc
other line in file
To keep only the first 11 characters of lines starting with > while keeping all other lines:
$ sed -r '/^>/ s/(.{11}).*/\1/' file
line one with something or other
>1234567890
other line in file
To keep only the first eleven characters of lines starting with > and deleting all other lines:
$ sed -rn '/^>/ s/(.{11}).*/\1/p' file
>1234567890
The above was tested with GNU sed. For BSD sed, replace the -r option with -E.
Explanation:
/^>/ is a condition. It means that the command which follows only applies to lines that start with >
s/(.{11}).*/\1/ is a substitution command. It replaces the whole line with just the first eleven characters.
-r turns on extended regular expression format, eliminating the need for some escape characters.
-n turns off automatic printing. With -n in effect, lines are only printed if we explicitly ask them to be printed. In the second case above, that is done by adding a p after the substitute command.
Other forms:
$ sed -r 's/(>.{10}).*/\1/' file
line one with something or other
>1234567890
other line in file
And:
$ sed -rn 's/(>.{10}).*/\1/p' file
>1234567890

Sed N command appears to delete line if empty

This code removes newlines, then quotes and separates the characters.
Semicolon isn't working. Piping to a second sed does work, but the semicolon doesn't.
Script
# Piping works
echo "$1" | sed -r ':a;N;s/\n/\\n/;$!ba' | sed -r 's/(\\?.)/'"'\1',/g"
# Semicolon doesn't work on single lines
echo "$1" | sed -r ':a;N;s/\n/\\n/;$!ba;s/(\\?.)/'"'\1',/g"
# Skipping N command on single line works
echo "$1" | sed -r ':a;$bb;N;s/\n/\\n/;$!ba;:b;s/(\\?.)/'"'\1',/g"
Output:
$ wchar "test\n"
't','e','s','t','\n',
test\n
't','e','s','t','\n',
$ wchar "test
test"
't','e','s','t','\n','t','e','s','t',
't','e','s','t','\n','t','e','s','t',
't','e','s','t','\n','t','e','s','t',
The problem you run into is that the first line is also the last one (note that "test\n" does not contain a newline but a backslash), so the first N command is executed before any test whether the current line is the last one and ends up trying to fetch past the end.
Since all you're trying to do with the label and N loop is to assemble the file into the hold buffer (the replacement of the newlines can wait until afterwards), I suggest the following replacement:
echo -e "test\n" | sed -rn '1h;1!H;${x;s/\n/\\n/g; s/(\\?.)/'\''\1'\'', /g;p}'
This follows the basic pattern
sed -n '1 h; 1! H; $ { x; do stuff; p }'
...in other words, it reads the file into the hold buffer, swaps it back into the pattern space when the last line is being handled (i.e., when the whole file is in the hold buffer), does stuff with it and then prints the result. The s commands in place of do stuff are lifted from your code.