Tuesday, January 01, 2013

fahd.blog in 2012

Happy 2013!
I'd like to wish everyone a great start to an even greater new year!

During 2012, I posted 31 new entries on fahd.blog. I am also thrilled that I have more readers from all over the world too! Thanks for reading and especially for giving feedback.

Top 5 posts of 2012:

I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)

Monday, December 31, 2012

Sed: Mutli-Line Replacement Between Two Patterns

This post has some useful sed commands which can be used to perform replacements and deletes between two patterns across multiple lines. For example, consider the following file:
$ cat file
line 1
line 2
foo
line 3
line 4
line 5
bar
line 6
line 7
1) Replace text on each line between two patterns (inclusive):
To perform a replacement on each line between foo and bar, including the lines containing foo and bar, use the following:
$ sed '/foo/,/bar/{s/./x/g}' file
line 1
line 2
xxx
xxxxxx
xxxxxx
xxxxxx
xxx
line 6
line 7
2) Replace text on each line between two patterns (exclusive):
To perform a replacement on each line between foo and bar, excluding the lines containing foo and bar, use the following:
$ sed '/foo/,/bar/{/foo/n;/bar/!{s/./x/g}}' file
line 1
line 2
foo
xxxxxx
xxxxxx
xxxxxx
bar
line 6
line 7
3) Delete lines between two patterns (inclusive):
To delete all lines between foo and bar, including the lines containing foo and bar, use the same replacement sed command as shown above, but simply change the replacement expression to a delete.

$ sed '/foo/,/bar/d' file
line 1
line 2
line 6
line 7
4) Delete lines between two patterns (exclusive):
To delete all lines between foo and bar, excluding the lines containing foo and bar, use the same replacement sed command as shown above, but simply change the replacement expression to a delete.
$ sed '/foo/,/bar/ {/foo/n;/bar/!d}' file
line 1
line 2
foo
bar
line 6
line 7
5) Replace all lines between two patterns (inclusive):
To perform a replacement on a block of lines between foo and bar, including the lines containing foo and bar, use:
$ sed -n '/foo/{:a;N;/bar/!ba;N;s/.*\n/REPLACEMENT\n/};p' file
line 1
line 2
REPLACEMENT
line 6
line 7
How it works:
/foo/{                   # when "foo" is found
  :a                     # create a label "a"
    N                    # store the next line
  /bar/!ba               # goto "a" and keep looping and storing lines until "bar" is found
  N                      # store the line containing "bar"
  s/.*\n/REPLACEMENT\n/  # delete the lines
}
p                        # print
6) Replace all lines between two patterns (exclusive):
To perform a replacement on a block of lines between foo and bar, excluding the lines containing foo and bar, use:
$ sed -n '/foo/{p;:a;N;/bar/!ba;s/.*\n/REPLACEMENT\n/};p' file
line 1
line 2
foo
REPLACEMENT
bar
line 6
line 7
References:
Sed - An Introduction and Tutorial by Bruce Barnett

Saturday, December 22, 2012

Useless Use of Echo

Most of us are familiar with the Useless Use of Cat Award which is awarded for unnecessary use of the cat command. For example, in nearly all cases, cat file | command arg can be rewritten as <file command arg.

In a similar vein, this post is about the useless use of the echo command. In nearly all cases:

echo string | command arg
can be rewritten using a heredoc:
command arg << END
string
END
or, using a here-string:
command arg <<< string
Note: Here-strings are not portable (but most modern shells support them) so use the heredoc alternative shown above if you are writing a portable script!

Saturday, December 01, 2012

Spring: Creating a java.util.Properties Bean

The easiest way to create a java.util.Properties bean in Spring is with a PropertiesFactoryBean as shown in the example below:
<bean id="emailProperties"
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="properties">
    <value>
        smtp.host=mail.host.com
        from=joe.bloggs@domain.com
        to=${mail.recipients}
    </value>
  </property>
</bean>
Spring will parse the key=value pairs and put them into the Properties object.

Saturday, November 24, 2012

Parsing a CSV file into JavaBeans using OpenCSV

opencsv is a very useful CSV parsing library for Java.

The following generic utility method shows how you can parse a CSV file into a list of JavaBeans.

/**
 * Parses a csv file into a list of beans.
 *
 * @param <T> the type of the bean
 * @param filename the name of the csv file to parse
 * @param fieldDelimiter the field delimiter
 * @param beanClass the bean class to map csv records to
 * @return the list of beans or an empty list there are none
 * @throws FileNotFoundException if the file does not exist
 */
public static <T> List<T> parseCsvFileToBeans(final String filename,
                          final char fieldDelimiter,
                          final Class<T> beanClass) throws FileNotFoundException {
  CSVReader reader = null;
  try {
    reader = new CSVReader(new BufferedReader(new FileReader(filename)),
                           fieldDelimiter);
    final HeaderColumnNameMappingStrategy<T> strategy =
                                         new HeaderColumnNameMappingStrategy<T>();
    strategy.setType(beanClass);
    final CsvToBean<T> csv = new CsvToBean<T>();
    return csv.parse(strategy, reader);
  } finally {
    if (reader != null) {
      try {
          reader.close();
      } catch (final IOException e) {
          // ignore
      }
    }
  }
}
Example:
Consider the following CSV file containing person information:
FirstName,LastName,Age
Joe,Bloggs,25
John,Doe,30
Create the following Person bean to bind each CSV record to:
public class Person {

  private String firstName;
  private String lastName;
  private int age;

  public Person() {
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
}
Now, you can parse the CSV file into a list of Person beans with this one-liner:
List<Person> persons = Utils.parseCsvFileToBeans("/path/to/persons.csv", 
                                                 ',', Person.class);