Hubot matching on multiple tokens per line? - coffeescript

How can I match on multiple occurrences of a token in a single message.
module.exports = (robot) ->
robot.hear /ITEM=(\d+)/, (msg) ->
msg.send 'matched='+msg.match
I would like to be able to match:
blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah
However I only get the first match with above code:
match=blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah,ITEM=100
I can always just take the message and manually parse each line for each item, but it seems that using robot.hear should be able to do it.

Use the two-step method, but you can do some things to make it a little more concise:
coffee> input = "blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah"
'blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah'
coffee> match = input.match /blah blah blah ((ITEM=\d+\s*)+) blah blah$/
[ 'blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah',
'ITEM=100 ITEM=200 ITEM=300',
'ITEM=300',
index: 0,
input: 'blah blah blah ITEM=100 ITEM=200 ITEM=300 blah blah' ]
coffee> match[1].match /(ITEM=\d+)/g
[ 'ITEM=100',
'ITEM=200',
'ITEM=300' ]

You can avoid the intermediate match by using the g flag on the regex passed to hear. For example:
module.exports = (robot) ->
robot.hear /ITEM=(\d+)/g, (msg) ->
msg.send 'matched='+msg.match.join(',')
All the matches are then available in msg.match.

Related

Is there a way to get sed to match the maximum string?

So I have a file that contains many instances of something like foo., foo.., foo..., and so on. I would like to replace them all with bar.
The command I used was sed -i 's/foo\.+/bar/g' abc.c. However, it seems like sed only matches the minimal string, so foo.. is replaced by bar., foo... with bar.. and so on.
Is there a way to get sed to do what I want?
Of the 4 proposals in the comments, only half are correct, as follows:
Mac_3.2.57$cat abc.txt
0: foo
1: ifoo.
2: foo..
3: foo...
x: blah
inf: foo.........
Mac_3.2.57$#wrong-- matches "foo" followed by 0 or more "."s
Mac_3.2.57$sed 's/foo\.*/bar/g' abc.txt
0: bar
1: ibar
2: bar
3: bar
x: blah
inf: bar
Mac_3.2.57$#right-- matches "foo" followed by 1 or more "."s
Mac_3.2.57$sed -E 's/foo\.+/bar/g' abc.txt
0: foo
1: ibar
2: bar
3: bar
x: blah
inf: bar
Mac_3.2.57$#wrong-- matches "foo.+"
Mac_3.2.57$sed 's/foo\.\+/bar/g' abc.txt
0: foo
1: ifoo.
2: foo..
3: foo...
x: blah
inf: foo.........
Mac_3.2.57$#right-- matches "foo" followed by 1 or more "."s
Mac_3.2.57$sed -E 's/foo\.{1,}/bar/g' abc.txt
0: foo
1: ibar
2: bar
3: bar
x: blah
inf: bar
I would use what I consider the simplest: sed 's/foo..*/bar/g' abc.txt

org-mode export headlines levels only, not inline text

I am trying to export headline levels only to an ODT file, without the inline text under each heading.
[Org file structure]
* Heading 1
+ Blah Blah
** Heading 1.1
+ Blah Blah
- Blah Blah
* Heading 2
[Exported structure]
* Heading 1
** Heading 1.1
* Heading 2
You could easily cycle only through the headlines (S-tab) and then export with the option visible only. (C-v).

How to copy stem value to simple variable in REXX

I'm trying to copy the value of LINE.I to variable THIS_IS_A_COMMENT2 so I can use it my JCL.
The JCLs are properly generated and executed, but the line QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2 is completely ignored.
The SAY "VALUE OF LINE.I : " LINE.I works just fine, I can't figure out to copy the value of LINE.I to a simple variable.
THIS_IS_A_COMMENT = "HELLO"
THIS_IS_A_COMMENT2 = ""
DO I = 1 TO LINE.0
SAY "VALUE OF LINE.I : " LINE.I
THIS_IS_A_COMMENT2 = LINE.I
QUEUE "//USERIDK JOB 0000,'HELLO',"
QUEUE "// CLASS=T,"
QUEUE "// MSGCLASS=X,"
QUEUE "// MSGLEVEL=(1,1),"
QUEUE "// USER=USERID,"
QUEUE "// PASSWORD="
QUEUE "//* THIS IS A COMMENT : " THIS_IS_A_COMMENT
QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2
QUEUE "//STEP1 EXEC PGM=IEFBR14"
QUEUE "//DD1 DD DUMMY"
QUEUE "/*"
QUEUE "$$"
O = OUTTRAP("OUTPUT.",,"CONCAT")
"SUBMIT * END($$)"
O = OUTTRAP(OFF)
END
I use the following jcl to submit my rexx code:
//JCLSAYHI JOB 00000,'SAY HI',
// CLASS=T,
// MSGCLASS=X,
// MSGLEVEL=(1,1),
// USER=MYUSER,PASSWORD=
/*JOBPARM R=H101,T=999,L=9999,S=ANY
//*----------------------------------------------
//STEPREXX EXEC PGM=IKJEFT01,PARM='SAYHI3'
//SYSEXEC DD DISP=SHR,DSN=MYUSER.REXX
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
//MYDATA DD DISP=SHR,DSN=MYUSER.REXX.DATASET
The SYSEXEC executes the code above, and the MYUSER.REXX.DATASET dataset contains:
********************************* Top of Data ******
HELLO1
HELLO2
HELLO3
HELLO4
HELLO5
******************************** Bottom of Data ****
TRACE results
Found the problem (REXX doesn't add double quotes at the end of the THIS IS A COMMENT2 line, so the line is ignored in the generated JCL). Just not sure how to fix that:
27 *-* QUEUE "//* THIS IS A COMMENT : " THIS_IS_A_COMMENT
>>> "//* THIS IS A COMMENT : HELLO"
28 *-* QUEUE "//* THIS IS A COMMENT2 : " THIS_IS_A_COMMENT2 ""
>>> "//* THIS IS A COMMENT2 : HELLO1 <--- DOUBLE QUOTE MISSING AT THE END HERE

How to replace several lines but not the last

I need to remove lines from word "WORDA" to the last "}" before WORDB.
But there are other "}" before. So SED missed the selection.
...
WORDA
{
blah
{
blahblah
...
blahblahblah
}
}
WORDB 0
...
So I'm trying to replace from "WORDA" to "WORDB" with "WORDB" but I lose the "0" at the end... The result is not inserted... All the last line is replaced.
(Of course, this "0" value can be any other number.)
sed.exe -i /WORDA/,/WORDB/c\WORDB\ file
result
...
WORDB
...
but I need:
...
WORDB 0
...
Any idea?
Crude but effective:
sed '/WORDA/,/WORDB/{/WORDB/!d;}' filename

How does one extract a unified-diff style patch subset?

Every time I want to take a subset of a patch, I'm forced to write a script to only extract the indices that I want.
e.g. I have a patch that applies to sub directories
'yay' and 'foo'.
Is there a way to create a new patch or apply only a subset of a patch? i.e. create a new patch from the existing patch that only takes all indices that are under sub directory 'yay'. Or all indices that are not under sub directory 'foo'
If I have a patch like ( excuse the below pseudo-patch):
Index : foo/bar
yada
yada
- asdf
+ jkl
yada
yada
Index : foo/bah
blah
blah
- 28
+ 29
blah
blah
blah
Index : yay/team
go
huskies
- happy happy
+ joy joy
cougars
suck
How can I extract or apply only the 'yay' subdirectory like:
Index : yay/team
go
huskies
- happy happy
+ joy joy
cougars
suck
I know if I script up a solution I'll be re-inventing the wheel...
Take a look at the filterdiff utility, which is part of patchutils.
For example, if you have the following patch:
$ cat example.patch
diff -Naur orig/a/bar new/a/bar
--- orig/a/bar 2009-12-02 12:41:38.353745751 -0800
+++ new/a/bar 2009-12-02 12:42:17.845745951 -0800
## -1,3 +1,3 ##
4
-5
+e
6
diff -Naur orig/a/foo new/a/foo
--- orig/a/foo 2009-12-02 12:41:32.845745768 -0800
+++ new/a/foo 2009-12-02 12:42:25.697995617 -0800
## -1,3 +1,3 ##
1
2
-3
+c
diff -Naur orig/b/baz new/b/baz
--- orig/b/baz 2009-12-02 12:41:42.993745756 -0800
+++ new/b/baz 2009-12-02 12:42:37.585745735 -0800
## -1,3 +1,3 ##
-7
+z
8
9
Then you can run the following command to extract the patch for only things in the a directory like this:
$ cat example.patch | filterdiff -i 'new/a/*'
--- orig/a/bar 2009-12-02 12:41:38.353745751 -0800
+++ new/a/bar 2009-12-02 12:42:17.845745951 -0800
## -1,3 +1,3 ##
4
-5
+e
6
--- orig/a/foo 2009-12-02 12:41:32.845745768 -0800
+++ new/a/foo 2009-12-02 12:42:25.697995617 -0800
## -1,3 +1,3 ##
1
2
-3
+c
Here's my quick and dirty Perl solution.
perl -ne '#a = split /^Index :/m, join "", <>; END { for(#a) {print "Index :", $_ if (m, yay/team,)}}' < foo.patch
In response to sigjuice's request in the comments, I'm posting my script solution. It isn't 100% bullet proof, and I'll probably use filterdiff instead.
base_usage_str=r'''
python %prog index_regex patch_file
description:
Extracts all indices from a patch-file matching 'index_regex'
e.g.
python %prog '^evc_lib' p.patch > evc_lib_p.patch
Will extract all indices which begin with evc_lib.
-or-
python %prog '^(?!evc_lib)' p.patch > not_evc_lib_p.patch
Will extract all indices which do *not* begin with evc_lib.
authors:
Ross Rogers, 2009.04.02
'''
import re,os,sys
from optparse import OptionParser
def main():
parser = OptionParser(usage=base_usage_str)
(options, args) = parser.parse_args(args=sys.argv[1:])
if len(args) != 2:
parser.print_help()
if len(args) == 0:
sys.exit(0)
else:
sys.exit(1)
(index_regex,patch_file) = args
sys.stderr.write('Extracting patches for indices found by regex:%s\n'%index_regex)
#print 'user_regex',index_regex
user_index_match_regex = re.compile(index_regex)
# Index: verification/ring_td_cte/tests/mmio_wr_td_target.e
# --- sw/cfg/foo.xml 2009-04-30 17:59:11 -07:00
# +++ sw/cfg/foo.xml 2009-05-11 09:26:58 -07:00
index_cre = re.compile(r'''(?:(?<=^)|(?<=\n))(--- (?:.*\n){2,}?(?![ #\+\-]))''')
patch_file = open(patch_file,'r')
all_patch_sets = index_cre.findall(patch_file.read())
patch_file.close()
for file_edit in all_patch_sets:
# extract index subset
index_path = re.compile('\+\+\+ (?P<index>[\w_\-/\.]+)').search(file_edit).group('index').strip()
if user_index_match_regex.search(index_path):
sys.stderr.write("Index regex matched index: "+index_path+"\n")
print file_edit,
if __name__ == '__main__':
main()