Replace string between square brackets with sed - string

I have some strings in a textfile that look like this:
[img:3gso40ßf]
I want to replace them to look like normal BBCode:
[img]
How can I do that with sed? I tried this one but it doesn't do anything:
sed -i 's/^[img:.*]/[img]/g' file.txt

Escape those square brackets
Square brackets are metacharacters: they have a special meaning in POSIX regular expressions. If you mean [ and ] literally, you need to escape those characters in your regexp:
$ sed -i .bak 's/\[img:.*\]/\[img\]/g' file.txt
Use [^]]* instead of .*
Because * is greedy, .* will capture more than what you want; see Jidder's comment. To fix this, use [^]]*, which captures a sequence of characters up to (but excluding) the first ] encountered.
$ sed -i .bak 's/\[img:.[^]]\]/\[img\]/g' file.txt
Are you using an incorrect sed -i syntax?
(Thanks to j.a. for his comment.)
Depending on the flavour of sed that you're using, you may be allowed to use sed -i without specifying any <extension> argument, as in
$ sed -i 's/foo/bar/' file.txt
However, in other versions of sed, such as the one that ships with Mac OS X, sed -i expects a mandatory <extension> argument, as in
$ sed -i .bak 's/foo/bar/' file.txt
If you omit that extension argument (.bak, here), you'll get a syntax error. You should check out your sed's man page to figure out whether that argument is optional or mandatory.
Match a specific number of characters
Is there a way to tell sed that there are always 8 random characters after the colon?
Yes, there is. If the number of characters between the colon and the closing square bracket is always the same (8, here), you can make your command more specific:
$ sed -i .bak 's/\[img:[^]]\{8\}\]/\[img\]/g' file.txt
Example
# create some content in file.txt
$ printf "[img:3gso40ßf]\nfoo [img:4t5457th]\n" > file.txt
# inspect the file
$ cat file.txt
[img:3gso40ßf]
foo [img:4t5457th]
# carry out the substitutions
$ sed -i .bak 's/\[img:[^]]\{8\}\]/\[img\]/g' file.txt
# inspect the file again and make sure everything went smoothly
$ cat file.txt
[img]
foo [img]
# if you're happy, delete the backup that sed created
$ rm file.txt.bak

Related

Eliminate multiple space from a file and modify the original file

Specify the command that removes multiple spaces from a text file, leaving a single space in their place. Extra requirements : Original file to be modified.
Managed to pull out those 3 commands:
awk '{$2=$2};1' filename.txt
tr -s '[:space:]' < filename.txt > filename.new && mv filename.new filename.txt
sed -i 's/\s\+/ /g' filename.txt
Not sure if using a 'temporary file' is the best way to do the trick. Is there any more efficient way to do the problem ? Doesn't matter if it is tr / sed / awk or anything else, you can post all of them.
Example input:
I'm just giving spaces
Output :
I'm just giving spaces
Edit: Still looking for more answers
I'd use ed over the non-standard sed -i (And non-portable RE in your example) if you want to alter the original file:
printf "%s\n" '1,$s/[[:space:]]\{2,\}/ /g' w | ed -s filename.txt
or with perl:
perl -pi -e 's/\s{2,}/ /g' filename.txt
The {2,} regular expression construct (\{2,\} for POSIX Basic Regular Expressions like sed and ed use) matches 2 or more of the previous token.
Both of these match any whitespace characters, not just space, because that's how your examples work. If the goal is to only compress multiple spaces, not spaces + tabs, switch out the [[:space:]] and \s for just a single space.
(Anything that modifies a file "in place", be it ed, sed -i, perl -i, or a regular editor, has a good chance that it's going to be using a temporary file under the hood, by the way. They just handle it for you so you don't have to do it manually like with your tr example.)

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

Trying to use grep to find something, then output a different part of the line

Say for instance I'm searching a line that is like this:
Color asdf
and I use grep to find that line, like grep asdf file.txt
How would I then display Color? Learning linux is hard.
With the command line tool sed you can replace stings by using regular expressions:
echo "Color asdf" | sed 's/\([^ ]*\).*/\1/'
This part: \([^ ]*\).* is a regular expresion. The first part of the regex: [^ ]*, matches any character except a space as many times as possible and what's between the \( and \) is being captured in the variable \1. Then you also match the remaining part of the string with .* and replace all of that with only the first word which was captured by \([^ ]*\) by using \1 in the replace part of the sed command.
Here some more info about sed:
http://linux.about.com/od/commands/a/Example-Uses-Of-Sed-Cmdsedxa.htm
You could use sed:
sed -n 's/[[:space:]][[:space:]]*asdf$//p' file.txt
Details:
The -n option tells sed not to print the pattern space automatically. Basically, it doesn't output anything unless you tell it to.
The s command of sed replaces text. Here, if a line ends with asdf, preceded by at least one whitespace character, we replace all of that with nothing and then print the line (notice the p flag at the end of the s command). The printing is only done if something was actually replaced. More information about the s command can be found e. g. in the GNU sed manual.
Edit for clarity: When using single quotes, parameter expansion does not work and thus, variables won't be replaced. To use variables, use double quotes:
search=asdf
sed -n "s/[[:space:]][[:space:]]*${search}\$//p" file.txt
If you'd really like to use grep here, you could pipe the output from grep into cut:
grep -h asdf *.txt | cut -s -d -f 1
Note that there have to be two spaces after the -d option to cut - the first tells cut to use a blank as the field delimiter (I'm assuming your fields are blank-delimited rather than tab-delimited), while the second separates the -d option from the following option (-f).
But, yeah, sed or awk are probably your friends here... :-)
you can color pattern in the line using grep
grep --colour -o 'asdf' file.txt
edit: the -o option will print only the patterns

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-

Search and replace with sed when dots and underscores are present

How do I replace foo. with foo_ with sed simply running
sed 's/foo./foo_/g' file.php
doesn't work.
Escape the .:
sed 's/foo\./foo_/g' file.php
Example:
~$ cat test.txt
foo.bar
~$ sed 's/foo\./foo_/g' test.txt
foo_bar
Interestingly, if you want to search for and replace just the dot, you have to put the dot in a character set. Escaping just the dot alone in a sed command for some reason doesn't work. The dot is still expanded to a single character wild card.
bash --version # Ubuntu Lucid (10.04)
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Replaces all characters with dash:
echo aa.bb.cc | sed s/\./-/g
# --------
Replaces the dots with a dash:
echo aa.bb.cc | sed s/[.]/-/g
# aa-bb-cc
With the addition of leading characters in the search, the escape works.
echo foo. | sed s/foo\./foo_/g # works
# foo_
Putting the dot in a character set of course also works.
echo foo. | sed s/foo[.]/foo_/g # also works
# foo_
Escape the dot with a \
sed 's/foo\./foo_/g' file.php
If you find the combination of / and \ confusing you can use another 'separator' character
sed 's#foo\.#foo_#g
The 2nd character after the s can be anything and sed will use that character as a separator.
You need to escape the dot - an unescaped dot will match any character after foo.
sed 's/foo\./foo_/g'
For myself, sed 's/foo\./foo_/g' is working. But you can also try:
sed -e 's/foo\./foo_/g'
and
sed -e "s/foo\\./foo_/g"
and
sed 's/foo[.]/foo_/g'

Resources