I want to run ,multiple regex commands in pipe on gvim.
for example:
s/,/;
s/\v\[(\d+):0\]/\=submatch(1)+1/g
how can i implement it in one line? does gvim support two regex commands in pipe?
i tried to run:
s/,/; | s/\v\[(\d+):0\]/\=submatch(1)+1/g
however it doesn't work for me.
hope for help
thanks :)
does gvim support two regex commands in pipe?
"Bars" are not about "regexes". They are about individual commands (see :h :bar for a complete list; also you may want to read :h cmdline-lines in full). But it actually works for :s, as per Vim's help: "Note that this is confusing (inherited from Vi): With ":g" the '|' is included in the command, with ":s" it is not."
however it doesn't work for me
That's because you must close the first regex before starting the second command: :s/,/;/ | ...
But in general, if you need to have "a bar" after a command which forcefully treats it as an argument, you can quote it with :h :execute, like this: execute 'cmd1' | cmd2. Beware of extra quoting single-quotes though.
Multiple command in one line You have to do this:
:command1 | :command2 | :command3 | and more...
for example
:retab | :%s/match/replace/g | :let tmp = 'something text' | :echo tmp
Don't forget the colon before the command
Related
I have the following in my .vimrc which (I believe) makes :grep within Vim use rg:
if executable('rg')
set grepprg=rg\ --no-heading\ --vimgrep\ --hidden\ --case-sensitive\ --ignore-vcs\ --glob\ '!.git'\ --glob\ '!node_modules'
endif
I want to search for all definitions of functions named render.... If I do
rg -e \(const\|let\)\ render .
on the command line, I get what I'm looking for.
But
:grep -e \(const\|let\)\ render
in vim results in
zsh:1: command not found: let) render
regex parse error:
(const
^
error: unclosed group
I've tried some other combos of \, putting the whole query in /.../, can't quite get it working.
How do I use the alternation operator in ripgrep in vim?
There are three pieces of machinery involved, here, each with its own idiosyncrasies: Vim, your shell, and RipGrep.
Ideally, this is how your pattern should look with RipGrep's syntax:
(let|const) render
If you try it as-is:
:grep (let|const) render
you should get a cascade of messages (irrelevant lines removed):
:!rg (let 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/26
/opt/local/bin/bash: -c: line 1: syntax error near unexpected token `let'
/opt/local/bin/bash: -c: line 1: `rg (let 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/26'
shell returned 2
E40: Can't open errorfile
/var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/26
Vim
The first line:
:!rg (let 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/26
^^^^^^^
tells you that the command executed under the hood is:
rg (let
which is obviously incomplete. That is because Vim thinks that the | is a command separator (:help :bar) so it tries to execute the broken :grep (let. If you want your | to pass through, you must escape it:
:grep (let\|const) render
OK, all the arguments are now passed to rg:
:!rg (let|const) render 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/27
^^^^^^^^^^^^^^^^^^^^^
Your shell
You are not done yet, though:
/opt/local/bin/bash: -c: line 1: syntax error near unexpected token `let'
/opt/local/bin/bash: -c: line 1: `rg (let|const) render 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/27'
shell returned 2
E40: Can't open errorfile /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/27
Your pattern includes a capture group delimited with parentheses, which confuses the hell out of your shell because it looks like an attempt to execute the command let|const in a subshell, which is bound to fail anyway, but in a context where it can't be done.
You can try to solve those problems by escaping things with backslashes but you are entering an escaping arms race between the shell and Vim. That is the kind of race where there is no winner.
A better approach is to wrap your whole pattern with single quotes:
:grep '(let\|const) render'
which tells your shell to treat what is between the quotes literally, without trying to be smart.
You can check what arguments are passed to rg by forcing an error:
:grep '(let\|const) render' foobar
which should show you this:
:!rg '(let|const) render' foo 2>&1| tee /var/folders/q4/8ckdmdb136z10l1nh7ss_hsw0000gn/T/vphU3gH/29
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Well done!
RipGrep
Without the single quotes, RipGrep wouldn't know that render is part of the pattern so it treats it as a filename and you get errors because that filename doesn't exist.
Wrapping the pattern in single quotes killed two birds with one stone: your shell expansion issue is solved and RipGrep knows where your pattern ends.
NOTE: While it is inconsequential, here, the -e flag is not necessary because your pattern doesn't start with a -.
I have some 'fastq' format DNA sequence files (basically just text files) like this:
#Sample_1
ACTGACTGACTGACTGACTGACTGACTG
ACTGACTGACTGACTGACTGACTGACTG
+
BBBBBBBBBBBBEEEEEEEEEEEEEEEE
EHHHHKKKKKKKKKKKKKKNQQTTTTTT
#
+
#
+
#Sample_4
ACTGACTGACTGACTGACTGACTGACTG
ACTGACTGACTGACTGACTGACTGACTG
+
BBBBBBBBBBBBEEEEEEEEEEEEEEEE
EHHHHKKKKKKKKKKKKKKNQQTTTTTT
My ultimate goal is to turn these into 'fasta' format files, but to do that I need to get rid of the two empty sequences in the middle.
EDIT
The desired output would look like this:
#Sample_1
ACTGACTGACTGACTGACTGACTGACTG
ACTGACTGACTGACTGACTGACTGACTG
+
BBBBBBBBBBBBEEEEEEEEEEEEEEEE
EHHHHKKKKKKKKKKKKKKNQQTTTTTT
#Sample_4
ACTGACTGACTGACTGACTGACTGACTG
ACTGACTGACTGACTGACTGACTGACTG
+
BBBBBBBBBBBBEEEEEEEEEEEEEEEE
EHHHHKKKKKKKKKKKKKKNQQTTTTTT
All of the dedicated software I tried (Biopython, stand alone programs, perl scripts posted by others) crash at the empty sequences. This is really just a problem of searching for the string #\n+ and replacing it with nothing. I googled this and read several posts and tried about a million options with sed and couldn't figure it out. Here are some things that didn't work:
sed s/'#'/,/'+'// test.fastq > test.fasta
sed s/'#,+'// test.fastq > test.fasta
Any insights would be greatly appreciated.
PS. I've got a Mac.
Try:
sed "/^[#+]*$/d" test.fastq > test.fasta
The /d option tells sed to "delete" the matching line (i.e. not print it).
^ and $ mean "start of string" and "end of string" respectively, i.e. the line must be an exact match.
So, the above command basically says:
Print all lines that do not only contain # or +, and write the result to test.fasta.
Edit: I misunderstood the question slightly, sorry. If you want to only remove pairs of consecutive lines like
#
+
then you need to perform a multi-line search and replace.
Although this can be done with sed, it's perhaps easier to use something like a perl script instead:
perl -0pe 's/^#\n\+\n//gm' test.fastq > test.fasta
The -0 option turns Perl into "file slurp" mode, where Perl reads the entire input file in one shot (instead of line by line). This enables multi-line search and replace.
The -pe option allows you to run Perl code (pattern matching and replacement in this case) and display output from the command line.
^#\n\+\n is the pattern to match, which we are replacing with nothing (i.e. deleting).
/gm makes the substitution multiline and global.
You could also instead pass -i as the first parameter to perl, to edit the file inline.
This may not be the most elegant solution in the world, but you can use tr to replace the \n with a null character and back.
cat test.fastq | tr '\n' '\0' | sed 's/#\x0+\x0//g' | tr '\0' '\n' > test.fasta
Try this:
sed '/^#$/{N;/\n+$/d}' file
When # is found, next line is appended to the pattern space with N.
If $ is found in next line, the d command deletes both lines.
I've switched to ACK-GREP recently (bye, bye standard grep) and the only thing I'm missing is the option to ignore whitespaces while searching.
Example:
#param(
'lol', int, "Foo bar",
can=False, hasBurger=True
)
and I want to find it by
ack #param('lol'
What do I have to change/add in .ackrc to force this behawior?
You can't. It is not due to the space but the new line. From the FAQ at the man page:
*Can I do multi-line regexes?*
No, ack does not support regexes that match multiple lines. Doing so would require
reading in the entire file at a time.
However, you can build your own pipe and delete all spaces:
cat YOURFILE | tr -d [:space:] | ack --type=TYPE -o PATTERN
But I guess, this is not exactly what you want.
I am trying to Use the GREP command to list all lines which contain the letter
'd' at least twice in a row (that is, next to each other), from file "test". But i can't get it to work. Can someone please help?
I can't display what I want. And am not sure how this works. I tried grep [dd] but that didn't work.
This is extremely confusing for me
In regex:
^ character means, start of data line.
all characters match themselves.
So, if you are trying to find lines starting with 'dd', try:
grep ^dd <your_file>
However if you just interested in finding out lines with 'dd' pattern, try:
grep dd <your_file>
The following should make it:
grep dd <your_file>
Your grep [dd] was specifying any line with a character from the set (set = []) containing "d" and "d". So simply putting them side-by-side without the square brackets provides the method for all lines containing a "d" with another "d" right after it.
cat yourfile | grep dd
grep dd yourfile
grep dd <yourfile
should all work, assuming you replace "yourfile" with your file's name.
If you really were looking for lines starting with two or more "d"s, using Sagar's "^dd" instead of just "dd". Similarly, you could use "dd$" for lines ending with two or more "d"s.
You might try "man regexp" or http://www.zytrax.com/tech/web/regex.htm for some more info.
I am attempting to parse (with sed) just First Last from the following DN(s) returned by the DSCL command in OSX terminal bash environment...
CN=First Last,OU=PCS,OU=guests,DC=domain,DC=edu
I have tried multiple regexs from this site and others with questions very close to what I wanted... mainly this question... I have tried following the advice to the best of my ability (I don't necessarily consider myself a newbie...but definitely a newbie to regex..)
DSCL returns a list of DNs, and I would like to only have First Last printed to a text file. I have attempted using sed, but I can't seem to get the correct function. I am open to other commands to parse the output. Every line begins with CN= and then there is a comma between Last and OU=.
Thank you very much for your help!
I think all of the regular expression answers provided so far are buggy, insofar as they do not properly handle quoted ',' characters in the common name. For example, consider a distinguishedName like:
CN=Doe\, John,CN=Users,DC=example,DC=local
Better to use a real library able to parse the components of a distinguishedName. If you're looking for something quick on the command line, try piping your DN to a command like this:
echo "CN=Doe\, John,CN=Users,DC=activedir,DC=local" | python -c 'import ldap; import sys; print ldap.dn.explode_dn(sys.stdin.read().strip(), notypes=1)[0]'
(depends on having the python-ldap library installed). You could cook up something similar with PHP's built-in ldap_explode_dn() function.
Two cut commands is probably the simplest (although not necessarily the best):
DSCL | cut -d, -f1 | cut -d= -f2
First, split the output from DSCL on commas and print the first field ("CN=First Last"); then split that on equal signs and print the second field.
Using sed:
sed 's/^CN=\([^,]*\).*/\1/' input_file
^ matches start of line
CN= literal string match
\([^,]*\) everything until a comma
.* rest
http://www.gnu.org/software/gawk/manual/gawk.html#Field-Separators
awk -v RS=',' -v FS='=' '$1=="CN"{print $2}' foo.txt
I like awk too, so I print the substring from the fourth char:
DSCL | awk '{FS=","}; {print substr($1,4)}' > filterednames.txt
This regex will parse a distinguished name, giving name and val a capture groups for each match.
When DN strings contain commas, they are meant to be quoted - this regex correctly handles both quoted and unquotes strings, and also handles escaped quotes in quoted strings:
(?:^|,\s?)(?:(?<name>[A-Z]+)=(?<val>"(?:[^"]|"")+"|[^,]+))+
Here is is nicely formatted:
(?:^|,\s?)
(?:
(?<name>[A-Z]+)=
(?<val>"(?:[^"]|"")+"|[^,]+)
)+
Here's a link so you can see it in action:
https://regex101.com/r/zfZX3f/2
If you want a regex to get only the CN, then this adapted version will do it:
(?:^|,\s?)(?:CN=(?<val>"(?:[^"]|"")+"|[^,]+))