Click here to Skip to main content
15,894,362 members
Articles / Programming Languages / Javascript

JsGrep - an OO-ish implementation of grep in JScript

Rate me:
Please Sign up or sign in to vote.
4.67/5 (3 votes)
4 Dec 20032 min read 38.9K   536   16  
Shows how the object features of JScript can be put to use in a useful utility script
///////////////////
// Helper functions
///////////////////

function DoNothing1(varDummy1) {}
function DoNothing2(varDummy1, varDummy2) {}

////////////
// "Classes"
////////////

// Counter

function Count_FilePreamble(strFile, bIsOnlyFile)
{
	this.cFileMatches = 0;
}

function Count_Action(strLine)
{
	++this.cFileMatches;
	++this.cTotalMatches;
	
	return this.bCountReqd;
}

function Count_FilePostamble(strFile, bIsOnlyFile)
{
	if (bIsOnlyFile)
	{
		if (this.bCountReqd)
			WScript.Echo(this.cFileMatches);
		else
			WScript.Echo('Match found');
	}
	else if (this.cFileMatches > 0)
	{
		if (this.bCountReqd)
			WScript.Echo(strFile + ": " + this.cFileMatches);
		else
			WScript.Echo(strFile);
	}
}

function Count_ProgPostamble(bOneFileOnly)
{
	if (this.bCountReqd && !bOneFileOnly)
		WScript.Echo('Total: ' + this.cTotalMatches);
}

function Counter(bCountReqd)
{
	// properties
	this.bCountReqd		= bCountReqd;
	this.cFileMatches	= 0;
	this.cTotalMatches	= 0;

	// methods
	this.FilePreamble	= Count_FilePreamble;
	this.Action			= Count_Action;
	this.FilePostamble	= Count_FilePostamble;
	this.ProgPostamble	= Count_ProgPostamble;
}

// Printer

function Print_Action(strLine)
{
	if (bSingleFile)
		WScript.Echo((this.bNumbered ? nLineNumber : '') + strLine);
	else
		WScript.Echo(strCurrFile + (this.bNumbered ? '(' + nLineNumber + ')' : '') + ': ' + strLine);
	
	return true;
}

function Printer(bNumbered)
{
	// properties
	this.bNumbered		= bNumbered;

	// methods
	this.FilePreamble	= DoNothing2;
	this.Action			= Print_Action;
	this.FilePostamble	= DoNothing2;
	this.ProgPostamble	= DoNothing1;
}

///////////////
// Main program
///////////////

var mapOpts =
{
	'c' : false // (c)ount
,	'i' : false // (i)gnore case
,	'l' : false // (l)ist files
,	'n' : false // show line (n)umbers
,	'r' : false // (r)ecursively match file names
,	'v' : false // in(v)ert match (i.e. show non-matching lines)
};

var i, cArgs = WScript.Arguments.length;
var nFirstNonOptArg = cArgs;

for (i = 0; i < cArgs; ++i)
{
	var strArg = WScript.Arguments(i);
	if (strArg == '--')
	{
		// end of args flag (to allow REs beginning with '-')
		nFirstNonOptArg = ++i;
		break;
	}
	else if (strArg.charAt(0) == '-')
	{
		var j, cChars = strArg.length;
		for (j = 1; j < cChars; ++j)
			mapOpts[strArg.charAt(j)] = true;
	}
	else
	{
		nFirstNonOptArg = i;
		break;
	}
}

if (nFirstNonOptArg == cArgs)
{
	// No RE
	WScript.Echo('usage: jsgrep [-cilnrv] regexp [file ...]');
	WScript.Quit(1);
}

var arrFiles = new Array();
var oShell = null;

for (i = nFirstNonOptArg + 1; i < cArgs; ++i)
{
	var strFileArg = WScript.Arguments(i);
	if (strFileArg.indexOf('*') >= 0 || strFileArg.indexOf('?') >= 0)
	{
		if (oShell == null)
			oShell = new ActiveXObject('WScript.Shell');
		var nLastSep = strFileArg.lastIndexOf('\\');
		var strPath = (nLastSep >= 0) ? strFileArg.slice(0, ++nLastSep) : '';
		var strCmd = 'cmd.exe /c dir /b ';
		if (mapOpts['r'])
			strCmd += '/s ';
		var procGlob = oShell.Exec(strCmd + strFileArg);
		while (!procGlob.StdOut.AtEndOfStream)
		{
			if (mapOpts['r'])
				arrFiles[arrFiles.length] = procGlob.StdOut.ReadLine();
			else
            	arrFiles[arrFiles.length] = strPath + procGlob.StdOut.ReadLine();
		}
	}
	else
		arrFiles[arrFiles.length] = strFileArg;
}

var cFiles = arrFiles.length;

if (cFiles == 0)
{
	if (nFirstNonOptArg < cArgs - 1)
	{
		WScript.Echo('no matching files found');
		WScript.Quit(1)
	}
	else
	{
		arrFiles[0] = '-'; // stdin
		cFiles = 1;
	}
}

var bSingleFile = (cFiles == 1);

var re = new RegExp(WScript.Arguments(nFirstNonOptArg), mapOpts['i'] ? 'i' : '');
var bInvertMatch = mapOpts['v'];

var oAction	= mapOpts['c'] ? new Counter(true) : mapOpts['l'] ? new Counter(false) : new Printer(mapOpts['n']);

var strCurrFile = '', nLineNumber = 1;
var oFSO = new ActiveXObject('Scripting.FileSystemObject');
var ts;

for (i = 0; i < cFiles; ++i)
{
	strCurrFile = arrFiles[i];
	var bNeedClose = false;

	if (strCurrFile == '-')
	{
		ts = WScript.stdin;
	}
	else
	{
		try
		{
			ts = oFSO.OpenTextFile(strCurrFile);
			bNeedClose = true;
		}
		catch(e)
		{
			WScript.Echo('Failed to open "' + strCurrFile + '" - ' + e.description);
			continue;
		}
	}

	nLineNumber = 1;
	oAction.FilePreamble(strCurrFile, bSingleFile);
	
	var bContinue = true;

	while (bContinue && !ts.AtEndOfStream)
	{
		var strLine = ts.ReadLine();

		if ((strLine.match(re) == null) == bInvertMatch)
			bContinue = oAction.Action(strLine);

		++nLineNumber;
	}

	oAction.FilePostamble(strCurrFile, bSingleFile);

	if (bNeedClose) ts.Close();
}

oAction.ProgPostamble(bSingleFile);

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Technical Lead Google
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions