UNIX ports - CUT

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
Download the ZIPped sources for all versions

 

Versions:

 

CUT.PL, Version 1.11 for Perl

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";
	}
}

Back to the top of this page...

 

CUT.CMD, Version 2.01 for OS/2 Rexx


/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* 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

Back to the top of this page...

 

CUT.REX, Version 0.50 beta for Regina Rexx


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*   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

Back to the top of this page...