Perl6 multithreaded spurt problems - multithreading

I write program which generates "random" text files where 3 words substituted with keys stored in $keysfilename file. Keys file has very simple structure, like
ASD123ASD
QWE123QWE
XZC123ZXC
Problem happens when I use more than one thread, for example
my #threads = (^32).map({
If fails on arbitrary file, with error
started
Thread<17>(14) got 1
Thread<18>(15) got 2
Thread<20>(17) got 17
Thread<5>(2) got 3
Thread<16>(13) got 4
Thread<21>(18) got 5
Thread<3>(0) got 6
Thread<8>(5) got 7
Thread<12>(9) got 10
Thread<11>(8) got 8
Thread<9>(6) got 9
Thread<14>(11) got 11
Thread<15>(12) got 12
Unhandled exception: Failed to open file C:\c\perltests\00000017.txt: no such file or directory
Thread<10>(7) got 13
Thread<13>(10) got 14
Thread<7>(4) got 15
Thread<19>(16) got 16
Thread<4>(1) got 0
Thread<6>(3) got 18
Thread<22>(19) got 19
at <unknown>:1 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:4294967295)
Thread<23>(20) got 20
Thread<24>(21) got 21
from gen/moar/m-CORE.setting:22337 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:34)
Thread<26>(23) got 22
Thread<25>(22) got 23
Thread<27>(24) got 24
from gen/moar/m-CORE.setting:22374 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:FALLBACK:35)
Thread<28>(25) got 25
Thread<29>(26) got 26
from gen/moar/m-Metamodel.nqp:3041 (C:\rakudo\share\nqp\lib/Perl6/Metamodel.moarvm::13)
Thread<30>(27) got 27
Thread<16>(13) got 28
Thread<17>(14) got 29
Thread<5>(2) got 30
Thread<18>(15) got 31
Thread<14>(11) got 32
Thread<15>(12) got 33
from gen/moar/m-CORE.setting:25189 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:226)
Thread<30>(27) got 58
Thread<29>(26) got 57
Unhandled exception: Failed to open file C:\c\perltests\00000028.txt: no such file or directory
Thread<28>(25) got 56
from gen/moar/m-CORE.setting:25203 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:92)
Thread<25>(22) got 55
from gen/moar/m-CORE.setting:25199 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:44)
Thread<27>(24) got 54
from gen/moar/m-CORE.setting:25506 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:96)
Thread<26>(23) got 53
from gentexts.pl:54 (<ephemeral file>::189)
Thread<24>(21) got 52
Thread<23>(20) got 51
Unhandled exception: Failed to open file C:\c\perltests\00000058.txt: no such file or directory
Thread<6>(3) got 50
Thread<22>(19) got 49
at <unknown>:1 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:4294967295)
Thread<34>(31) got 48
from gen/moar/m-CORE.setting:22337 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:34)
Thread<33>(30) got 47
Thread<4>(1) got 46
from gen/moar/m-CORE.setting:22374 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:FALLBACK:35)
Thread<7>(4) got 45
from gen/moar/m-Metamodel.nqp:3041 (C:\rakudo\share\nqp\lib/Perl6/Metamodel.moarvm::13)
Thread<19>(16) got 44
Thread<11>(8) got 43
at <unknown>:1 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:4294967295)
Thread<8>(5) got 42
from gen/moar/m-CORE.setting:22337 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:throw:34)
Thread<12>(9) got 41
Thread<10>(7) got 40
from gen/moar/m-CORE.setting:25189 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:226)
Thread<13>(10) got 39
from gen/moar/m-CORE.setting:25203 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:92)
Thread<31>(28) got 37
from gen/moar/m-CORE.setting:25199 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:44)
Thread<32>(29) got 38
Thread<9>(6) got 36
from gentexts.pl:44 (<ephemeral file>::15)
Thread<3>(0) got 35
Thread<21>(18) got 34
from gen/moar/m-CORE.setting:22374 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:FALLBACK:35)
Thread<17>(14) got 59
from gen/moar/m-CORE.setting:25506 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:spurt:96)
Thread<5>(2) got 60
Thread<18>(15) got 61
from gentexts.pl:54 (<ephemeral file>::189)
Thread<9>(6) got 85
Thread<32>(29) got 84
from gen/moar/m-CORE.setting:30638 (C:\rakudo/share/perl6/runtime/CORE.setting.moarvm:THREAD-ENTRY:44)
System Win 10 x32, Rakudo 6.c
my $keysfilename := 'C:/c/keysfile.txt';
my $output := 'C:/c/perltests';
my #keys = ();
for $keysfilename.IO.words {
#keys.push($_);
}
my $len := elems #keys;
my $lorem = q:to/END/;
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada purus vel tincidunt eleifend. Fusce sollicitudin augue augue, et gravida dolor varius a. Vestibulum iaculis, dui iaculis iaculis molestie, tellus ante hendrerit massa, at volutpat risus metus vitae nisi. Integer neque magna, ultrices eu erat at, efficitur sollicitudin sem. Aliquam sed purus malesuada, porta est eu, rutrum neque. Quisque dolor leo, condimentum non mollis eget, tristique eget odio. Donec dignissim magna nec imperdiet iaculis. Vestibulum lorem ligula, euismod ac porttitor faucibus, rutrum eu ex.
Donec scelerisque nisi eget risus condimentum ultrices. Integer porta maximus quam, in lobortis quam fermentum eu. Morbi eu ligula consequat, aliquam sem eget, sollicitudin eros. Suspendisse potenti. Cras finibus metus et eros accumsan, id vehicula libero lobortis. Aenean vulputate lacinia urna at fringilla. Nulla id tincidunt lectus, quis accumsan lorem. In posuere magna non purus hendrerit rutrum. Maecenas in mattis tellus. Maecenas vel feugiat enim. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin convallis dapibus tellus vitae euismod. Nam eleifend dui quam, eget lobortis quam pulvinar id. Cras euismod posuere dolor non ultricies.
Ut dapibus porta faucibus. Duis velit ante, tincidunt id velit id, imperdiet egestas velit. Morbi efficitur enim dignissim interdum egestas. Vivamus eu urna condimentum, aliquam orci non, ullamcorper est. Phasellus egestas at tellus nec tristique. Fusce feugiat commodo faucibus. In hac habitasse platea dictumst. Quisque dignissim, mauris a pellentesque dictum, mauris velit tincidunt lorem, sed tincidunt libero enim vitae orci. Nam interdum, ante nec consequat vulputate, nisi turpis euismod nibh, sit amet elementum nunc diam non eros. Proin quis viverra risus. Vestibulum vestibulum diam in velit consectetur, eu elementum lacus sagittis. Morbi accumsan ac ante eget faucibus. In nec elit bibendum, tristique enim non, sodales ex. Donec sodales erat vitae odio cursus commodo.
Vestibulum felis lacus, mattis eget porta eget, mattis ut felis. Pellentesque aliquet, purus eu semper suscipit, sem ipsum euismod nunc, sed dapibus augue sem vel elit. Etiam tincidunt arcu ut nisi tempor commodo. Mauris at eros tincidunt, fringilla erat nec, sagittis ante. Integer et malesuada quam. Cras vel porta erat, sit amet efficitur erat. Praesent blandit purus quis urna consectetur, eget ultricies ipsum pulvinar. Phasellus ac molestie elit. Vestibulum et tincidunt velit. Aliquam a venenatis ipsum, nec commodo libero. Nullam eget consectetur lectus. Morbi placerat interdum erat nec interdum.
Morbi bibendum dui eu turpis pretium, eget aliquet augue aliquam. Aliquam eu dignissim mauris, vitae placerat augue. Ut sed tortor sit amet augue imperdiet rutrum. Aliquam erat volutpat. Morbi a turpis in sapien ultrices tristique. Proin quis vestibulum lorem, ut pharetra ex. Quisque tempor bibendum purus ac vehicula. Suspendisse tellus ipsum, imperdiet id sodales vel, congue a leo. Nulla gravida tincidunt nisi eu tempor. Mauris imperdiet tempor ante eget rutrum. Nam ut dui at augue laoreet mollis. Sed metus elit, viverra ac fringilla vel, fermentum et magna. Nam ligula purus, pretium vel dignissim vitae, fermentum at urna. Nullam ac ullamcorper felis. Maecenas dapibus consequat mi.
END
my #words = $lorem.split(' ');
my $wordlen = #words.elems;
my &getNext = sub {
my $counter = 0;
my Lock $lock .= new;
return sub (#filename) {
$lock.lock;
if ($counter < 100_000) {
#filename[0] = $counter;
$counter++;
}
$lock.unlock;
};
}();
say "started";
my #threads = (^1).map({
Thread.start(
name => $_,
sub {
loop {
my #counter = (-1);
getNext(#counter);
last if #counter[0] < 0;
say $*THREAD ~ " got " ~ #counter[0];
my #copy = #words.clone;
for (^3) {
my $pos = $wordlen.rand.round;
#copy[$pos] = #keys[$len.rand.round];
}
spurt sprintf($output ~ '/%08d.txt', #counter[0]), #copy.join(' ');
}
}
);
}).join;

A few notes.
This:
my #keys = ();
for $keysfilename.IO.words {
#keys.push($_);
}
is really just this: my #keys = $keysfilename.IO.words;
and this: #keys[$len.rand.round]
is really just this:#keys.pick
I'm not quite sure what you're doing with the counter array, it seems
like you just want files 0..99999.
You are making locks inside your subroutine for each thread. If you
want to keep multiple threads from accessing something, make one lock
outside and have each one of them use it to lock the exclusive code.
You're also using Thread to make threads, but that is really a
pretty low level interface. Try to use the higher level constructs
before falling to that level if possible.
In this case, it seems like you just want to split up the 100,000 file
creations into multiple threads just to get some parallelism. There
are a few constructs that make that really easy, hyper and
race. Since you don't even really care what order the files are
created in, you can just use race and it will churn them out as fast
as possible.
You can use the 'degree' parameter to race to say how many
threads you want to use. (You might need to set RAKUDO_MAX_THREADS to
get the behavior you want).
my $keysfilename := 'C:/c/keysfile.txt';
my $output := 'C:/c/perltests';
my #keys = $keysfilename.IO.words;
my $lorem = q:to/END/;
Lorem ipsum ...
END
my #words = $lorem.split(' ');
my $wordlen = #words.elems;
[^100000].race(degree => 32).map({
# say $*THREAD ~ " got " ~ $_;
my #copy = #words;
for (^3) {
my $pos = $wordlen.rand.round;
#copy[$pos] = #keys.pick;
}
spurt sprintf($output ~ '/%08d.txt', $_), #copy.join(' ');
});

There is almost never a reason to use Threads directly in Perl 6, there are plenty of features that do the hard work for you. In most cases the simplest improvement is to just use start instead of Thread.start, and await LIST instead of LIST».join or LIST.map(*.join).
You were calling List.join not Thread.join, which may be at least partially why you were having problems.
There are many more things that make this difficult to read and understand.
by how you wrote getNext it seems like you know only or mostly only JavaScript. This is how I would write it.
sub get-next (#filename) {
state Int $counter = 0; # set to zero only the first time it is called
state Lock $lock .= new;
$lock.protect: ->{
if $counter < 100_000 {
#filename[0] = $counter++;
}
}
}
except that you are only using #filename to bypass the default readonly semantics of parameters.
sub get-next ($filename is rw) {
state Int $counter = 0;
state Lock $lock .= new;
$lock.protect: ->{
if $counter < 100_000 {
$filename = $counter++;
}
}
}
except that it would make more sense to just return the value.
sub get-next () {
state Int $counter = 0;
state Lock $lock .= new;
$lock.protect: ->{
$counter++ if $counter < 100_000
} // Nil
# the `if` will return `Empty` when $counter gets too big
# but we want `Nil` instead
}
This either returns the counter or Nil which is an undefined value so you can use it like this:
loop {
my $counter = get-next() orelse last;
…
}
Since you only ever use the sub in a loop, it could just call last itself.
Or better yet if you instead changed the line that declared the counter to
state Int $counter = 0 but True;
Then you could change the loop to a while loop, with no need to add last anywhere.
while get-next() -> $counter { … }
Now that I showed you how you can improve getNext, I'm going to throw it away and use much nicer features of Perl 6.
(It would have made more sense to use a Channel by the way)
# will probably still work with `use v6.c;`
# but v6.d has a better system backing `await`
use v6.d.PREVIEW;
# override the original default number of threads
# (16 threads currently)
BEGIN %*ENV<RAKUDO_MAX_THREADS> //= 32;
# the "correct" way to do this is setting $*SCHEDULER
# but this is easier
my $keys-filename = 'C:/c/keysfile.txt';
my $output-dir = 'C:/c/perltests';
my #keys = $keys-filename.IO.words;
my #lorem = q:to/EOF/.split(' ');
…
EOF
say 'started';
END say 'finished';
for race ^100_000 -> $counter {
say $*THREAD, " got ", $counter;
my #copy = #lorem; # no need for .clone
for (^+#copy).pick(3) -> $pos {
#copy[$pos] = #keys.roll;
}
spurt $*SPEC.catfile($output-dir, $counter.fmt('/%08d.txt')), #copy.join(' ');
}
( I ran a test, and it never gave a Thread id higher than 6 )
I used race rather than hyper because the return values are thrown away anyway.
If it didn't work, you have a buggy version of Rakudo. If so I would recommend updating to the latest release v2017.02
(say $*PERL.compiler.version;)
+#array is the same as #array.elems
^ NUMBER is the same as 0 ..^ NUMBER which is sugar for
Range.new( 0, NUMBER, :excludes-max )
This still has the problem that some of the “words” have extra characters.
amet, elit. and ex.␤␤Donec for example
…
my #pos = ($lorem ~~ m:ex/ « \w+: /).map: { .from, .chars }
# #pos looks something like [(0,5),(6,5),(12,5),(18,3),…]
…
for race ^100_000 -> $counter {
say $*THREAD, " got ", $counter;
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
my $copy = $lorem;
# sort so that the transforms are done from the end of the string
# towards the beginning of the string
for #pos.pick(3).sort.reverse {
$copy.substr-rw( |$_ ) = #keys.roll;
}
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
spurt $*SPEC.catfile($output-dir, $counter.fmt('/%08d.txt')), $copy;
}

Related

Trouble with recommended work-around for COUNTIF > 255 characters

I cannot get the MS recommended 'work-around' for COUNTIF/COUNTIFS criteria greater than 255 characters to produce any result beyond a worksheet #VALUE! error.
Source: COUNTIF function
Wrong value returned The COUNTIF function returns incorrect results when you use it to match stringsfor long strings longer than 255 characters. To match strings longer than 255 characters, use the CONCATENATE function or the concatenate operator &. For example, =COUNTIF(A2:A5,"long string"&"another long string")
Sample text string with a 504 character length string in A2:A5,
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur et mi congue, ullamcorper, nulla non, interdum augue. Etiam at turpis sagittis, auctor ante quis, imperdiet neque. Nulla ut mauris ac enim rutrum congue. Vivamus elementum nisi et lectus scelerisque bibendum. Mauris tristique condimentum purus, dictum sagittis velit. Cras non purus ut magna placerat suscipit nec sit amet est. Nam finibus sed nibh ac euismod. Nam fermentum mattis quam, a commodo elit suscipit nec. In eu ipsum iaculis.
Formula per support.office.com recommendations,
'this exceeds 255 character limit
=countif(a:a, a2)
'this is the recommended work-around
=countif(a:a, left(a2, 255)&mid(a2, 256, 255))
'alternate for a2 < 256 characters
=countif(a:a, left(a2, 255)&iferror(mid(a2, 256, 255), text(,)))
Result should be 4. I cannot get anything but #VALUE! if A2 contains any text with a length longer than 255.
Hard-coding the first 255 characters suffixed with the second remaining 249 characters does nothing but return the same #VALUE! error.
=COUNTIF(A:A, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur et mi congue, ullamcorper, nulla non, interdum augue. Etiam at turpis sagittis, auctor ante quis, imperdiet neque. Nulla ut mauris ac enim rutrum congue. Vivamus elementum nisi et lectus s"&"celerisque bibendum. Mauris tristique condimentum purus, dictum sagittis velit. Cras non purus ut magna placerat suscipit nec sit amet est. Nam finibus sed nibh ac euismod. Nam fermentum mattis quam, a commodo elit suscipit nec. In eu ipsum iaculis.")
I guess you want a question. Does this work at all? What am I missing? Is it my xl2010/xl2016 versions? The documentation I've referred to seems current.
Addendum:
If this does not work as described (or even as imagined) then a proof of a broken concept is easily an acceptable answer.
This will do strings up to 508 character fairly reliably.
=COUNTIFS(D1:D5,LEFT(D1,254)&"*",D1:D5,"*" &RIGHT(D1,254))
It will, in fact, do larger strings by comparing the last 254 and the first 254. Which may or may not suffice for individual requirements.
But may give false positives if the search parameters are shorter than 255 and, the to be searched ends and begins with the same text. For example test test will be counted twice if A1 is test.

Extract colon delimited fields/values from text file with awk/sed/cut/grep

I would like to extract from a text file some delimited field/values that come in pairs, they might appear in any position in a line or paragraph. The file might contain several long or short paragraphs. I want the output either as one only row per file or row per occurrence. I have performed several options where I have managed to obtain the first occurrence of a fieldname or the second one but not both of them. I can get the N fieldname in one "pass" and then I need to run a second one for the following fieldname with order related issues.
Any suggestions to get this done in one line command?
Text File 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed faucibus orci justo, quis faucibus arcu scelerisque molestie.
Curabitur :Field1 Value1: lacus at scelerisque :Field2 Value2: aliquam. Aenean mattis elit et magna volutpat, eu finibus justo cursus.
Etiam non cursus nisi. Donec urna nulla, convallis ut velit sit amet, accumsan faucibus urna. :Field1 Value2: lacinia lectus :Field3 Value2: bibendum ligula dictum gravida. Duis eget metus sed lorem scelerisque varius.
Text File 2
Duis leo sem, placerat eget :Field3 Value1: volutpat eget, condimentum at odio. Ut iaculis tincidunt massa, in :Field1 Value2: accumsan nulla bibendum quis. Sed tincidunt justo sit amet est bibendum mollis. Fusce gravida nunc a nibh blandit ullamcorper. Aliquam auctor laoreet pellentesque :Field1 Value1:
Quisque tempor ultrices congue.
Mauris feugiat est sed neque malesuada tincidunt. Pellentesque fringilla, nunc vitae porta tempor, mauris felis ultricies eros, ac hendrerit lacus odio et nisi. Vivamus cursus lacinia nunc, a mollis mi hendrerit a. Nunc commodo dui nec iaculis fringilla.
Desired output for Text File 1
FieldName1 Value2 FieldName2 Value2 FieldName1 Value1 FieldName3 Value2
FieldName1 Value2
FieldName2 Value2
FieldName1 Value1
FieldName3 Value2
Desired output for Text File 2
FieldName3 Value1 FieldName1 Value2 FieldName1 Value1
FieldName3 Value1
FieldName1 Value2
FieldName1 Value1
If you take colon as the field separator, you'll find that your placeholders are the even-numbered fields:
awk -F: '{for (i=2; i<=NF; i+=2) print $i}' file
will get you most of the way there.

Find and Replace Multiple occurrences of a string within a large string

I have a large string.
I want to find a specific tag from the large string and replace content within that tag. This tag could occur multiple times and has to be replaced each time.
Below is my code:
$FirstString = '<tag>'
$lastString = '</tag>'
$contentVal = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. <tag> Aha Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes</tag>, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, <tag> Aha imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus.</tag> Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. <tag> Aha Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum.</tag>"
if ($contentVal.Contains('<tag>')) {
$Pos1 = $contentVal.IndexOf($FirstString) + $FirstString.Length;
$Pos2 = $contentVal.IndexOf($lastString);
#Find text between <tag> and </tag>
$FoundString = $contentVal.Substring($Pos1, $Pos2 - $Pos1);
Write-Host $FoundString
#Modify this FoundString by finding Aha and replacing with <br/>
$FinalString = $FinalString.Replace("Aha","</br>")
Write-Host $FinalString
}
Now I want to append this $finalString to $contentVal at the same position at which it was earlier.
Also, I have multiple occurences of <tag>.
How to manipulate each occurence and append to main string?

Search from a string to another in Linux

I am trying to find a way to search from a string within a text to another string.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus massa nulla, lobortis sit amet placerat hendrerit, mollis quis nulla. Morbi consectetur, odio vel rhoncus euismod, nunc nisi euismod ante, vitae molestie ante nulla non est.
Vivamus eget fermentum lorem, sed suscipit nulla. Aliquam consequat ultrices maximus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Etiam vitae tortor quis lectus convallis ullamcorper. Nullam nec dignissim tellus, vel dictum nisi. Etiam sit amet libero vulputate, eleifend libero nec, semper ex. Cras eu magna fringilla, iaculis sapien id, feugiat lorem. Ut id velit mauris.
I'd like to know if there is a way, in the command line, to come up with what's in between the bolded words in the paragraph above.
I've tried different variations of grep without any success.
You can use parameter substitution:
#!/bin/bash
string=$( <dat/lorem.txt )
tmp=${string#*amet}
tmp=${tmp%tellus*}
echo $tmp
output:
$ string=$( <dat/lorem.txt ); tmp=${string#*amet}; tmp=${tmp%tellus*}; echo $tmp
, consectetur adipiscing elit. Phasellus massa nulla, lobortis sit amet placerat hendrerit,
mollis quis nulla. Morbi consectetur, odio vel rhoncus euismod, nunc nisi euismod ante,
vitae molestie ante nulla non est. Vivamus eget fermentum lorem, sed suscipit nulla.
Aliquam consequat ultrices maximus. Pellentesque habitant morbi tristique senectus et
netus et malesuada fames ac turpis egestas. Etiam vitae tortor quis lectus convallis
ullamcorper. Nullam nec dignissim
by one sed command
sed -n ':a;$!{N;ba};s/.*\(amet.*tellus\).*/\1/p' infile
amet placerat hendrerit, mollis quis nulla. Morbi consectetur, odio vel rhoncus euismod, nunc nisi euismod ante, vitae molestie ante nulla non est.
Vivamus eget fermentum lorem, sed suscipit nulla. Aliquam consequat ultrices maximus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Etiam vitae tortor quis lectus convallis ullamcorper. Nullam nec dignissim tellus
If you needn't the keywords in output:
sed -n ':a;$!{N;ba};s/.*amet\(.*\)tellus.*/\1/p' infile
placerat hendrerit, mollis quis nulla. Morbi consectetur, odio vel rhoncus euismod, nunc nisi euismod ante, vitae molestie ante nulla non est.
Vivamus eget fermentum lorem, sed suscipit nulla. Aliquam consequat ultrices maximus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Etiam vitae tortor quis lectus convallis ullamcorper. Nullam nec dignissim
Use sed for this one :
sed -n '/amet/,/tellus/p' atext.txt | sed 's/.*amet/amet/;s/tellus.*/tellus/'
Output should look like:
amet ...(everything in between)...tellus
The first sed deletes all lines except the ones that include the words amet and tellus, and everything in between.
The second sed deletes all words before amet, and all words after tellus
You can use a regular expression
grep -e 'amet .* tellus' yourfile
Where . matches any character except line breaks, and * means 0 or more times.

VIM Spellcheck, Within Quoted Strings - PHP

I was wondering if it would be possible to run the vim spell checker while coding with PHP.
I can run it if I disable syntax highlighting, and it highlights almost all methods/function names because they are not English words.
So, my question is this, can I run the spell check on just the strings within PHP files?
For example, just within the ' quotes (and " quotes), ignoring everything else:
$paragraph = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In est libero, dictum ut suscipit eget, lacinia in justo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent sit amet sem libero, in pretium enim. Pellentesque tortor ante, imperdiet quis mattis in, tincidunt et ligula. Cras porta velit a ligula venenatis placerat.';
$paragraph2 = "Vestibulum quis eleifend lectus. Vestibulum odio odio, mollis at eleifend a, adipiscing sed quam. Nam quis nisi quis mauris faucibus hendrerit eu a leo. Sed feugiat purus sit amet purus congue quis semper diam malesuada. Vivamus et enim non arcu pretium sollicitudin. Nullam blandit, lorem eu aliquet tincidunt, enim mauris placerat lectus, id faucibus nulla lectus non elit. Sed eget fermentum lacus. Ut tempus pulvinar neque, vel pellentesque purus aliquet quis. Vivamus molestie pretium quam at imperdiet. Maecenas diam turpis, malesuada ut sollicitudin ac, congue eleifend urna. Quisque id ipsum eget ipsum tempus blandit at vel magna. Fusce eu felis metus.";
see the vim help: :help spell-syntax
You can define particular syntax groups as having spell checking.
There's probably a better way to do it (using a ~/.vim/after/syntax/php.vim file?), but a simple hack is to make a personal version of the php syntax file in ~/.vim/syntax (you can do this by doing :e $VIMRUNTIME/syntax/php.vim and the :saveas ~/.vim/syntax/php.vim), and change all instances of the text contains=#phpAddStrings to contains=#Spell,#phpAddStrings. Next time you open a php file, turn on spell checking as normal with :set spell.

Resources