dreamsys software

JavaScript Shell Scripting Tutorial

Lists & Maps


When your scripts start getting more complex, you will find that you need to use data structures such as lists and maps (i.e. hashtables, hashmaps, dictionaries, etc). First we will cover lists, they are very simple to use in JavaScript.

Let's enhance our previous script on classes to now store a list of users.

#!/usr/bin/env node

var fs = require('fs');
var prompt = require('prompt');

prompt.start();

var users = [];

function User() {
	var self = this;

	self.name = '';
	self.age = 0;
	self.height = 0;
	self.weight = 0;

	self.display = function() {
		console.log('');
		console.log('User Information:');
		console.log('User Name     : ' + self.name);
		console.log('User Age      : ' + self.age);
		console.log('User Height   : ' + self.height);
		console.log('User Weight   : ' + self.weight);
	}

	self.loadFromInput = function() {
		prompt.get(['name', 'age', 'height', 'weight'], function(err, result) {
			if (err) throw err;

			self.name = result.name;
			self.age = result.age;
			self.height = result.height;
			self.weight = result.weight;

			users.push(self);
			createUsers();
		});
	}

	self.loadFromString = function(strUser) {
		var lines = strUser.split('\t');
		self.name = lines[0];
		self.age = lines[1];
		self.height = lines[2];
		self.weight = lines[3];
	}

	self.toString = function() {
		return self.name + '\t' + self.age + '\t' + self.height + '\t' + self.weight;
	}
}

var args = process.argv.slice(2);

var displayUsers = function() {
	console.log('');
	console.log('User List:');

	for (index in users) {
                var user = users[index];
		user.display();
	}
}

var saveUsers = function() {
	var fileContents = users.length + '\n';

	for (index in users) {
		var user = users[index];

		fileContents += user.toString() + '\n';
	}

	fs.writeFile('users.txt', fileContents, function(err) {
                if (err) throw err;
                console.log('users saved');
                displayUsers();
        });
}

var createUsers = function() {
	prompt.get([{
		name:'create_user',
		description: 'Create another user? (Y/N)'
		}], function(err, result) {
                        if (err) throw err;

			if (result.create_user == 'Y') {
				var user = new User();
				user.loadFromInput();
			} else {
				saveUsers();
			}
                });
}

var loadUsers = function() {
	var fileLines = fs.readFileSync('users.txt').toString().split('\n');
	var numUsers = fileLines[0];

	for (var i=1; i<=numUsers; i++) {
		var user = new User();
		user.loadFromString(fileLines[i]);
		users.push(user);
	}
}

if (args.length >= 1 && args[0] == 'READ') {
	createUsers();
} else {
	loadUsers();
	displayUsers();
}

Again the class object is created, this time there are two new functions in place of save() and loadFromFile(). There is loadFromString() to take the string object as a parameter instead of opening it in the function each time. Also there is toString() which will return the string representation of the user for saving to the file. The idea of this script is that it will loop while asking for you to enter user info until you enter "N", then it will quit and save the list. Again if you give the parameter "READ" to the script, it will prompt for input otherwise it will just load the users from the file.

In addition to our User class, we have several functions which are used for the program flow. The first function displayUsers() will display all users in the "users" array object created at the top of the file. In JavaScript an array is the same thing as a list.

The next function, saveUsers(), will create a string out of each of the users. First it will write the number of users to the first line in the file, then it will write each user as a single line on the file. The users fields are separated by a tab character. And each user is separated by a new line character.

The createUsers() function will prompt the user to enter user information, if they select Y then it will create a new user, if they select N then it will save the users to the file and print them. After a user is loaded from input, it calls the createUsers() function again. Since JavaScript is event based, you can't simply call the prompt function in a loop, you must loop in your events by calling the original function again.

The final function, loadUsers(), will load the users from the input file and add them to the users array list object.

Let's run this once to create some data and then again to read the data:

$ ./userTest.js READ
prompt: Create another user? (Y/N):  Y
prompt: name:  User1
prompt: age:  1
prompt: height:  2
prompt: weight:  3
prompt: Create another user? (Y/N):  Y
prompt: name:  User2
prompt: age:  4
prompt: height:  5
prompt: weight:  6
prompt: Create another user? (Y/N):  Y
prompt: name:  User3
prompt: age:  7
prompt: height:  8
prompt: weight:  9
prompt: Create another user? (Y/N):  N
users saved

User List:

User Information:
User Name     : User1
User Age      : 1
User Height   : 2
User Weight   : 3

User Information:
User Name     : User2
User Age      : 4
User Height   : 5
User Weight   : 6

User Information:
User Name     : User3
User Age      : 7
User Height   : 8
User Weight   : 9

The next data structure we will cover is the map, which works very much like an array in JavaScript. This type of data structure is where you map one variable to another. For instance, we could have a "properties" map, where we will set properties and then retrieve them when needed.

For this simple example we will create a properties map and use it to store properties for a URL that we will call and print the contents of.

#!/usr/bin/env node

var properties = [];

properties['protocol'] = 'http';
properties['host'] = 'www.google.com';
properties['port'] = '80';
properties['path'] = '/trends/';

//The properties in this map represent the URL:
//http://www.google.com:80/trends/

var url = properties['protocol'] + '://' +
	  properties['host'] + ':' +
	  properties['port'] +
	  properties['path'];

console.log('URL: ' + url);

Here we create a map named properties by initializing the variable with [], just like an array list object. We use a string for the key for the map, the following keys are used: 'protocol', 'host', 'port', 'path'. They are given a value so when we lookup the keys the values are returned.

The map is very flexible and this is just a simple illustration of how to use one. In the next section we will cover how to use enumerations in JavaScript.

Prev (Strings) | Next (Enums)


Blog Entries
Blob Entry 1
Blob Entry 2
Blob Entry 3
Blob Entry 4
Blob Entry 5
Blob Entry 6