CUT can help you filter screen output by cutting and displaying only specified words or substrings from its standard input.
General syntax:
some_program | CUT -C:column [ -L:length ]
or:
some_program | CUT -F:word [ -L:length ] [ -D:delimiter [ -I ] ]
| some_program | is the program whose output is to be filtered | |
| column | is the position of the first character of the substring to be captured | |
| word | is the first word to be captured | |
| length | is the number of characters or words to be captured (default is to end of line) | |
| delimiter | is the string that separates words (space is default); this option is not yet available in the Regina Rexx version | |
| -I | specifies case insensitive search for delimiter (default is case sensitive) |
Examples:
VER | REGINA CUT.REX -F:5 | REGINA CUT.REX -C:1 -L:4
or:
VER | PERL CUT.PL -F:5 | PERL CUT.PL -C:1 -L:4
will both display "5.00." for Windows 2000 SP3; they remove the "Microsoft Windows 2000" text, the brackets and the build number.
| Download the ZIPped sources for all versions |
For me this was my second large exercise in regular expressions.
I'm sure it could use some optimization, but for now it will have to do.
I liked the command line parsing bit most of all.
#! perl
$syntax = "\nCut.pl, Version 1.11\nPort of Unix' CUT command\n\n";
$syntax = $syntax."Usage:\n\nany_cmd | PERL CUT.PL [-DEBUG] ";
$syntax = $syntax."{-C:n|-F:n [-D:'any_string' [-I]]} [-L:n] [-S]\n\n";
$syntax = $syntax."Argument: Function:";
$syntax = $syntax." Dependency:\n";
$syntax = $syntax."========= =========";
$syntax = $syntax." ===========\n";
$syntax = $syntax."any_cmd command that's output is to be parsed";
$syntax = $syntax."\n-DEBUG display intermediate results\n";
$syntax = $syntax." (preferably the first argument)\n";
$syntax = $syntax."-C:<column_number> parse by Columns or Characters\n";
$syntax = $syntax."-D:'<delimiter>' Delimiter character or string";
$syntax = $syntax." -F\n";
$syntax = $syntax." (should be escaped if necessary)\n";
$syntax = $syntax."-F:<field_number> parse by Fields or words\n";
$syntax = $syntax."-I case Insensitive delimiter";
$syntax = $syntax." -D\n";
$syntax = $syntax."-L:<length> number of characters or words ";
$syntax = $syntax."to display -C\n";
$syntax = $syntax."-S Skip blank lines in result\n\n";
$syntax = $syntax."Written by Rob van der Woude\n";
$syntax = $syntax."http://www.robvanderwoude.com\n";
# Assign default values
$case = 1;
$debug = 0;
$delim = "\\s";
$help = 0;
$len = 0;
$skip = 0;
# Command line parsing is SO much easier using regular expressions
foreach $_ ( @ARGV ) {
if ( $debug == 1 ) {
print "$_\n";
}
SWITCH: {
if ( $_ =~ m/ˆ-C:(\d+)$/i ) {
$type = "char";
$char = $1;
last SWITCH;
}
if ( $_ =~ m/ˆ-D:\'?([ˆ.']+)\'?$/i ) {
$delim = $1;
last SWITCH;
}
if ( $_ =~ m/ˆ-DEBUG$/i ) {
$debug = 1;
print "\nCommand line arguments:\n$_\n";
last SWITCH;
}
if ( $_ =~ m/ˆ-F:(\d+)$/i ) {
$type = "word";
$word = $1;
last SWITCH;
}
if ( $_ =~ m/ˆ-I$/i ) {
$case = 0;
last SWITCH;
}
if ( $_ =~ m/ˆ-L:(\d+)$/i ) {
$len = $1;
last SWITCH;
}
if ( $_ =~ m/ˆ-S$/i ) {
$skip = 1;
last SWITCH;
}
$help = 1;
}
}
if ( !@ARGV[0] or ( $help == 1 ) ) {
print $syntax;
exit(1);
}
# Debug info
if ( $debug == 1 ) {
print "\nInterpretation of command line arguments:\n";
print "\$case=$case\n\$char=$char\n\$delim=$delim\n";
print "\$len=$len\n\$skip=$skip\n\$type=$type\n\$word=$word\n";
}
# Create the regular expressions to parse ("cut") the string
$re = "ˆ";
if ( $type eq "word" ) {
if ( $case == 0 ) {
$re = $re."ˆ(?i)";
}
$re = $re."(?:$delim)*";
if ( $word > 1 ) {
for ( $i = 1; $i < $word; $i++ ) {
$re = $re."[ˆ$delim]+(?:$delim)+";
}
}
$re = $re."(";
$re0 = $re.".*)\$";
if ( $len > 0 ) {
$re = $re."[ˆ$delim]+";
for ( $i = 1; $i < $len; $i++ ) {
$re = $re."(?:$delim)+[ˆ$delim]+";
}
$re = $re.")(?:$delim)";
} else {
$re = $re0;
}
if ( $case == 0 ) {
$re = $re."(?-i)";
}
} else {
# if ( $type eq "char" ) {
if ( $char > 0 ) {
$re = $re.".{".( $char - 1 )."}";
$re0 = $re."(.*)\$";
}
if ( $len > 0 ) {
$re = $re."(.{0,$len})";
} else {
$re = $re0;
}
}
# Debug info
if ( $debug == 1 ) {
print "\nRegular Expression:\n$re\n";
print "\nStandard input \& \"cut\" result:\n";
}
# Parse STDIN and display results
while ( <STDIN> ) {
chomp $_;
if ( $debug == 1 ) {
print "STDIN: $_\n";
}
$m = $_;
if ( $_ =~ $re ) {
print "$1\n";
} elsif ( $_ =~ $re0 ) {
print "$1\n";
} elsif ( $skip == 0 ) {
print "\n";
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Attempt to "port" the Unix CUT command to Rexx */
/* Rob van der Woude, May 16 1998 - June 4 2000 */
/* Usage: any_command | CUT { -C:n | -F:n */
/* [ -D:"any_string" [ -I ] ] } [ -L:n ] */
/* [ -S ] [ -V:varname ] [ -X:command ] */
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Load RexxUtil */
if RxFuncQuery( "SysLoadFuncs" ) <> 0 then do
call RxFuncAdd "SysLoadFuncs", "RexxUtil", "SysLoadFuncs"
call SysLoadFuncs
end
/* Parse and check command line */
parse arg cmdline
cmdline = translate( cmdline, '-', '/' )
parse value cmdline with cmdline'-x:'xcommand
if xcommand = "" then parse value cmdline with cmdline'-X:'xcommand
cmdline = strip( cmdline )
parse upper value cmdline with .'-C:'column .
parse value cmdline with .'-d:"'delimiter'"'.
if delimiter = '' then parse value cmdline with .'-D:"'delimiter'"'.
parse upper value cmdline with .'-F:'field .
parse upper value cmdline with .'-L:'length .
parse upper value cmdline with .'-V:'variable .
ipos = pos( ' -I', translate( cmdline ) )
if ipos = 0 then do
case = ''
end
else do
if ipos > lastpos( '"', cmdline ) | ipos < pos( '"', cmdline ) then do
case = 'upper'
delimiter = translate( delimiter )
end
else do
case = ''
end
end
spos = pos( ' -S', translate( cmdline ) )
if spos = 0 then do
skip = 0
end
else do
if spos > lastpos( '"', cmdline ) | spos < pos( '"', cmdline ) then do
skip = 1
end
else do
skip = 0
end
end
select
when column <> '' & field <> '' then call Syntax
when length <> '' & datatype( length, 'W' ) <> 1 then call Syntax
when field <> '' then do
if datatype( field, 'W' ) <> 1 then call Syntax
cuttype = 'WORD'
cutpos = field
end
when column <> '' then do
if delimiter <> '' then call Syntax
if datatype( column, 'W' ) <> 1 then call Syntax
cuttype = 'CHAR'
cutpos = column
end
otherwise call Syntax
end
cutlen = 0
if length <> '' then cutlen = length
if delimiter = '' then delimiter = ' '
if variable = '' then variable = 'CUT'
/* Purge variable */
call value variable, "", "OS2ENVIRONMENT"
/* Read Standard Input */
empty = 0
do i = 1 by 1 while lines( ) > 0
parse pull line.i
if line.i = "00"X then leave
if line.i = "1A"X then leave
if line.i <> "" then empty = 0
if line.i = "" then empty = empty + 1
/* Stop after 100 empty lines */
if empty > 100 then leave
end
/* Ignore those 100 empty lines */
line.0 = i - 100
/* Cut lines as specified on command line */
cuttot = cutpos + cutlen
do i = 1 to line.0
if line.i = "" then do
msg = ""
call Output
iterate
end
if cuttype = "CHAR" then do
linelen = length( line.i )
if linelen >= cutpos then do
select
when cutlen = 0 then do
msg = substr( line.i, cutpos )
call Output
end
when cutlen > 0 then do
if linelen < cuttot then do
msg = substr( line.i, cutpos )
call Output
end
else do
msg = substr( line.i, cutpos, cutlen )
call Output
end
end
otherwise call Syntax
end
end
else do
msg = ""
call Output
end
end
if cuttype = "WORD" & delimiter = " " then do
linelen = words( line.i )
if linelen >= cutpos then do
select
when cutlen = 0 then do
msg = subword( line.i, cutpos )
call Output
end
when cutlen > 0 then do
if linelen < cuttot then do
msg = subword( line.i, cutpos )
call Output
end
else do
msg = subword( line.i, cutpos, cutlen )
call Output
end
end
otherwise call Syntax
end
end
else do
msg = ""
call Output
end
end
if cuttype = "WORD" & delimiter <> " " then do
string = line.i
dlen = length( delimiter )
do j = 1 by 1 until string = ""
interpret 'parse '||case||' value string with word.'||j||'"'||delimiter||'"string'
word.0 = j
end
linelen = word.0
line = word.cutpos
if linelen > cutpos then do j = cutpos + 1 by 1 to linelen
line = line||delimiter||word.j
end
if linelen >= cutpos then do
select
when cutlen = 0 then msg = line
when cutlen > 0 then do
if linelen < cuttot then do
msg = line
end
else do
dpos = 0
do j = 1 to cutlen
dpos = pos( delimiter, line, dpos + dlen )
end
msg = substr( line, 1, dpos )
end
end
otherwise call Syntax
end
call Output
end
else do
msg = ""
call Output
end
end
end
EXIT
Output:
if skip = 0 | strip( msg ) <> "" then do
if xcommand <> "" then do
call value variable, msg, "OS2ENVIRONMENT"
address CMD "@CMD /C "||xcommand
end
else do
say msg
end
end
return
Syntax: procedure
call beep 220, 240
say
say " CUT, Version 2.01 for OS/2"
say " (C) 1998 - 2000, Rob van der Woude"
say " http://www.robvanderwoude.com"
say
say " Usage: <any_command> | CUT <options>"
say
say " Options: Function: Dependency"
say " __________________________________________________________________________"
say
say " -C:<column_number> Parse by Columns or Characters"
say ' -D:"<delimiter>" Delimiter character or string -F'
say " -F:<field_number> Parse by Fields or words"
say " -I Case Insensitive delimiter (should -D"
say " be the first or last parameter)"
say " -L:<string_length> Number of characters to display -C"
say " or -L:<fields> Number of fields (words) to display -F"
say " -V:<variable_name> Save last result in environment variable"
say
say " Examples:"
say
say " ECHO 1234567890 | CUT -C:4"
say
say ' VER | TIME | CUT -F:2 -D:":" -S -V:TIME -X:TEST.CMD'
say " (TEST.CMD should contain one line: ECHO Time is %TIME%)"
say
EXIT 1
end
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Attempt to "port" the Unix CUT command to Rexx */
/* Rob van der Woude, May 16 1998 - January 4 2003 */
/* Usage: */
/* any_command | CUT { -C:n | -F:n [ -D:"any_string" [ -I ] ] } [ -L:n ] */
/* Note: The -D switch isn't functional yet, so neither is -I */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Specify maximum number of empty lines */
maxEmpty = 50
/* Initialize RexxUtil */
If RxFuncQuery( "sysloadfuncs" ) <> 0 Then Do
Call RxFuncAdd "sysloadfuncs", "RexxUtil", "sysloadfuncs"
Call sysloadfuncs
End
/* Parse and check command line */
Parse arg cmdline
cmdline = Translate( cmdline, '-', '/' )
cmdline = strip( cmdline )
Parse Upper Value cmdline With .'-C:'column .
Parse Value cmdline With .'-d:"'delimiter'"'.
If delimiter = '' Then Parse Value cmdline With .'-D:"'delimiter'"'.
Parse Upper Value cmdline With .'-F:'field .
Parse Upper Value cmdline With .'-L:'length .
ipos = Pos( ' -I', Translate( cmdline ) )
If ipos = 0 Then Do
case = ''
End
Else Do
If ipos > LastPos( '"', cmdline ) | ipos < Pos( '"', cmdline ) Then Do
case = 'Upper'
delimiter = Translate( delimiter )
End
Else Do
case = ''
End
End
spos = Pos( ' -S', Translate( cmdline ) )
If spos = 0 Then Do
skip = 0
End
Else Do
If spos > LastPos( '"', cmdline ) | spos < Pos( '"', cmdline ) Then Do
skip = 1
End
Else Do
skip = 0
End
End
Select
When column <> '' & field <> '' Then Call Syntax
When length <> '' & DataType( length, 'W' ) <> 1 Then Call Syntax
When field <> '' Then Do
If DataType( field, 'W' ) <> 1 Then Call Syntax
cuttype = 'WORD'
cutpos = field
End
When column <> '' Then Do
If delimiter <> '' Then Call Syntax
If DataType( column, 'W' ) <> 1 Then Call Syntax
cuttype = 'CHAR'
cutpos = column
End
Otherwise Call Syntax
End
cutlen = 0
If length <> '' Then cutlen = length
If delimiter = '' Then delimiter = ' '
/* Read Standard Input */
empty = 0
Do i = 1 By 1 While Lines( ) > 0
line.i = LineIn( "STDIN" )
If line.i = "00"X Then Leave
If line.i = "1A"X Then Leave
If line.i = "" Then empty = empty + 1; Else empty = 0
/* Stop after <maxEmpty> empty lines */
If empty > maxEmpty Then Leave
End
/* Ignore those empty lines */
line.0 = i - empty
/* Cut lines as specified on command line */
cuttot = cutpos + cutlen
Do i = 1 to line.0
If line.i = "" Then Do
msg = ""
Call Output
Iterate
End
If cuttype = "CHAR" Then Do
linelen = Length( line.i )
If linelen >= cutpos Then Do
Select
When cutlen = 0 Then Do
msg = substr( line.i, cutpos )
Call Output
End
When cutlen > 0 Then Do
If linelen < cuttot Then Do
msg = substr( line.i, cutpos )
Call Output
End
Else Do
msg = substr( line.i, cutpos, cutlen )
Call Output
End
End
Otherwise Call Syntax
End
End
Else Do
msg = ""
Call Output
End
End
If cuttype = "WORD" & delimiter = " " Then Do
linelen = Words( line.i )
If linelen >= cutpos Then Do
Select
When cutlen = 0 Then Do
msg = SubWord( line.i, cutpos )
Call Output
End
When cutlen > 0 Then Do
If linelen < cuttot Then Do
msg = SubWord( line.i, cutpos )
Call Output
End
Else Do
msg = SubWord( line.i, cutpos, cutlen )
Call Output
End
End
Otherwise Call Syntax
End
End
Else Do
msg = ""
Call Output
End
End
If cuttype = "WORD" & delimiter <> " " Then Do
string = line.i
dlen = Length( delimiter )
Do j = 1 by 1 until string = ""
interpret 'Parse '||case||' Value string With word.'||j||'"'||delimiter||'"string'
word.0 = j
End
linelen = word.0
line = word.cutpos
If linelen > cutpos Then Do j = cutpos + 1 by 1 to linelen
line = line||delimiter||word.j
End
If linelen >= cutpos Then Do
Select
When cutlen = 0 Then msg = line
When cutlen > 0 Then Do
If linelen < cuttot Then Do
msg = line
End
Else Do
dpos = 0
Do j = 1 to cutlen
dpos = Pos( delimiter, line, dpos + dlen )
End
msg = substr( line, 1, dpos )
End
End
Otherwise Call Syntax
End
Call Output
End
Else Do
msg = ""
Call Output
End
End
End
/* Normal program end */
Exit 0
Output:
If skip = 0 | strip( msg ) <> "" Then Say msg
Return
Syntax: procedure
Call beep 220, 240
Say
Say "Cut.rex, Version 0.50 beta for Regina Rexx"
Say 'Attempt to "port" the Unix CUT command to Rexx'
Say
Say "Usage: <any_command> | CUT <options>"
Say
Say "Options: Function: Dependency"
Say "__________________________________________________________________________"
Say
Say " -C:<column_number> Parse by Columns or Characters"
/*
Say ' -D:"<delimiter>" Delimiter character or string -F'
*/
Say " -F:<field_number> Parse by Fields or words"
/*
Say " -I Case Insensitive delimiter (should -D"
*/
Say " be the first or last parameter)"
Say " -L:<string_length> Number of characters to display -C"
Say "or -L:<fields> Number of fields (words) to display -F"
Say
Say "Examples:"
Say
Say " ECHO 1234567890 | CUT -C:4"
Say " VER | DATE | REGINA CUT.REX -F:6"
Say " VER | DATE | REGINA CUT.REX -F:6 | REGINA CUT.REX -C:7"
Say
Say "Written by Rob van der Woude"
Say "http://www.robvanderwoude.com"
Exit 1
Return