Cucumber scenario with quotes in the text - cucumber

I'd like to have quotes in my scenario data. It's not working when that data has quotes in it. An example modified from The Cucumber Book would be:
Then I should see the "<message>" message
Examples:
| type | message |
| Swiss | I love Swiss cheese |
| Blue | I love "Blue" cheese |
| Cheddar | I love Cheddar cheese |
In my particular case I get an undefined step definition message because of "Blue" in the second scenario above. Is there a way I should be escaping the quotes? (I've tried backslashes but that didn't make any difference.)

My guess is that your current step definition looks like:
Then /I should see the "([^"]+)" message/ do |message|
p message
end
The [^"] tells the regex to match anything except double-quotes. This would be why your "Blue" example does not match.
Given that you are only looking for one argument, it would be safe to do:
Then /I should see the "(.*)" message/ do |message|
p message
end
Using (.*) would match everything between the quotes, including the quotes around Blue.

Related

Creating simple tables in vim

Recently I've started discovering "deeper" vim and now I want to create a simple table without using any external plugins (I know it's bad, but I want to have some "know-how").
Let's say I want to have a table like this:
| name | address | phone |
|---------------------------------------------------------|
| John Adams | 1600 Pennsylvania Avenue | 0123456789 |
|---------------------------------------------------------|
| Sherlock Holmes | 221B Baker Street | 0987654321 |
|---------------------------------------------------------|
But how do I manage to make underscores till the end of the longest line and seperate columns with equal width? (In short way, no typing all by hand)
If you know the amount of the dashes needed then you can do:
{number}i-<ESC>
Where {number} is the amount of dashes needed. If you want to "learn" that automatically then you need to use VimL and strlen() function to first learn how many dashes are needed and then you can use append() to insert text below provided line.

How do I match the inner pattern multiple times instead of the outer patterns that is similar?

I would like to match an inner patterns that are subsets of the greater outer pattern using egrep. For example:
$ egrep 'b.*a' <<< baababaa
baababaa
I want it to print:
baa
ba
baa
egrep isn't really the correct tool for the job due to grep limitations with output control. Instead, sed can provide exactly what you need using basic regular expressions.
For example:
$ echo "baababaa" | sed 's/\(.\)b/\1 b/g'
baa ba baa
Explanation
sed 's/find/replace/g' - general substitution form of sed with the 'g' option applied to make the replacements global, where
find
'.' - match any single-character, and
\(.\) - capture the single-character between the \(...\),
followed by a 'b',
replace
\1 insert the back-reference (the character captured between \(...\)),
followed by a ' ' (space) and 'b'.
A more limited form that simply finds all inner "ab" and puts a space between them would be:
sed 's/ab/a b/g'
Look things over and let me know if you have questions.

searching a multiple line pattern using grep regex

I am relatively new to linux I want to search a pattern in a file which starts with "Leonard is" and ends on "champion"
Also this pattern might be placed in multiple lines
the input file(input.txt) may look like:
1 rabbit eats carrot Leonard is a champion
2 loin is the king of
3 jungle Leonard is a
4 Champion
5 Leonard is An exemplary
6 Champion
i would want to have all the occurrences of my pattern ignoring all the other characters other than the pattern in the output file:
1 Leonard is a champion
3 Leonard is a
4 Champion
5 Leonard is An exemplary
6 Champion
i have been very close with the following command:
cat input.txt | grep -ioE "Leonard.*Champion$"
as this command only returns
1 Leonard is a champion
ignoring all the patterns occurring in multiple line
if any other approach of searching other than grep is useful kindly let me know Thanks!!
Perl to the rescue:
perl -l -0777 -e 'print for <> =~ /(.*Leonard(?s:.*?)[Cc]hampion.*)/g' -- input.txt
-l adds newlines to prints
-0777 reads the whole file instead of processing it line by line
the diamond operator <> reads the input
.*? is like .*, i.e. it matches anything, but the ? means the shortest possible match is enough. That prevents the regex from matching everything between the first Leonard and last Champion.
. in a regex doesn't match a newline normally, but it does with the s modifier. (?s:.*?) localizes the changed behaviour, so other dots still don't match newlines.
You're looking for \s which stands for whitespace. + stands for one or more
Pattern: Leonard is a\s+Champion
See: https://regex101.com/r/qiNXhf/1
I use this tool with 0 knowledge of regex in my mind, and it helps me a lot. See the notes on the right bottom, where all these signs are explained.
The "." is referenced as "any character except new line", therefore, what you're trying to achieve with . is not possible, I suggest using \s with an addition of * or + as well (as suggested above), but need to find out how to implement it with the "grep" reg expression. There are also nice tools for regex testing - https://regexr.com/ for example.

Find two lines and replace with one

I am looking for a solution that would allow me to search text files on a linux server that would look a file and find a pattern such as:
Text 123
Blue Green
And then replaces it with one line, every time it finds it in a file...
Order Blue Green
I am not sure what would be the easiest way to solve this. I have seen many guides using SED but only for finding one line and replacing it.
You ask about sed, here is an answer in sed.
Let me mention however, that while sed is fun for this kind of exercise, you probably should choose something else, more flexible and easier to learn; perl for example.
look for first line /Text 123/
when found start a loop :a
concat next line N
replace twins of searched text with single copy and print it
s/Text 123\nText 123/Text 123/p;
loop while that replaces ta;
try to replace s///
rely on concat being printed unchanged if replace does not trigger
Code:
sed "/Text 123/{:a;N;s/Text 123\nText 123/Text 123/p;ta;s/Text 123\nBlue Green/Order Blue Green/}"
Test input:
Text 123
Do not replace
Lala
Text 123
Blue Green
lulu
Text 123
Do not replace either
Text 123
Text 123
Blue Green
preceding should be replaced
Output:
Text 123
Do not replace
Lala
Order Blue Green
lulu
Text 123
Do not replace either
Text 123
Order Blue Green
preceding should be replaced
Platform: Windows and GNU sed version 4.2.1
Note:
On that platform the sed line allows to use the environment variables for the two text fragments, which you probably want to do:
sed "/%EnvVar2%/{:a;N;s/%EnvVar2%\n%EnvVar2%/%EnvVar2%/p;ta;s/%EnvVar2%\n%EnvVar%/Order %EnvVar%/}"
Platform2:
still Windows
using bash GNU bash, version 3.1.17(1)-release (i686-pc-msys)
GNU sed version 4.2.1 (same)
On this platform, variables can e.g. be used like:
sed "/${EnvVar2}/{:a;N;s/${EnvVar2}\n${EnvVar2}/${EnvVar2}/p;ta;s/${EnvVar2}\n${EnvVar}/Order ${EnvVar}/}"
On this platform it is important to use "..." in order to be able to use variables,
it does not work with '...'.
As #edMorton has hinted, on all platforms be careful however with trying to replace (using variables) text which looks like using a variable. E.g. with "Text $123" in bash. In that case, not using variables but trying to replace text which looks like variables, using '...' instead of "..." is the way to go.
sed is for simple substitutions on individual lines, that is all. If you find yourself trying to use constructs other than s, g, and p (with -n) then you are on the wrong track as all other sed constructs became obsolete in the mid-1970s when awk was invented.
Your problem is not doing substitutions on individual lines, it's on a multi-line record and to do that with GNU awk for multi-char RS is:
$ awk -v RS='^$' -v ORS= '{gsub(/Text 123\nBlue Green/,"Order Blue Green")}1' file
Order Blue Green
but there are several other approaches depending on your real needs.

Grep for a string in a specific order

I need to grep a large file for words (really a string of characters) in a specified order. I also need the string to be able to contain a colon ":". For example, if the words are "apple", "banana", and ":peach", I will get the line that says, "apple cherries banana cool :peach" but not "apple :peach cherries banana cool". I would really like to be able to have one string and not grep commands in other grep commands. I am not concerned about searching whole words only.
grep "apple.*banana.*:peach" file
e.g.
$ echo "apple cherries banana cool :peach" | grep "apple.*banana.*:peach"
apple cherries banana cool :peach
$ echo "apple :peach cherries banana cool" |grep "apple.*banana.*:peach"
$
Pretty simple regex. the "apple", "banana" and ":peach" portions are just literal strings. The .* in between them is are two regex operators - the . will match any character, and the * says that the previous match can match 0 or more times.
In essence we're saying find these literal strings in this order, with any number of characters between them (including none, so even "applebanana:peach" would match.)

Resources