How to access NEW or OLD field given only the field's name?
Actually, since NEW is a well defined composite type, you can just access any column with plain and simple attribute notation. SQL itself does not allow dynamic identifiers (table or column names etc.). But you can use dynamic SQL with EXECUTE in a PL/pgSQL function.
Demo
CREATE OR REPLACE FUNCTION trg_demo1()
  RETURNS TRIGGER AS
$func$
DECLARE
   _col_value text;
   _col_name  text := quote_ident(TG_ARGV[0]);  -- escape identifier
BEGIN
   EXECUTE format('SELECT ($1).%s::text', _col_name)
   USING NEW
   INTO  _col_value;

   -- do something with _col_value ...

   RAISE NOTICE 'It works. The value of NEW.% is &gt;&gt;%&lt;&lt;.', _col_name, _col_value;

   RETURN NEW;
END
$func$ LANGUAGE plpgsql;

The cast to text is optional. Using it, because it works universally. If you know the type, you can work without casting ...
Using format() with %s, because the identifier is already escaped at that point.
Else, use format() with %I to safeguard against SQL injection.
Alternatively, in Postgres 9.3 or later, you can convert NEW to JSON with to_json() and access columns as keys:
CREATE OR REPLACE FUNCTION trg_demo2()
  RETURNS TRIGGER AS
$func$
DECLARE
   _col_value text := to_json(NEW) -&gt;&gt; TG_ARGV[0];  -- no need to escape identifier
BEGIN
   RAISE NOTICE 'It works. The value of NEW.% is &gt;&gt;%&lt;&lt;.', TG_ARGV[0], _col_value;
   RETURN NEW;
END
$func$ LANGUAGE plpgsql;

Since the column name is not concatenated into an SQL string, SQL injection is not possible, and the name does not need to be escaped.
db&lt;&gt;fiddle here (with EXCEPTION instead of NOTICE to make the effect visible).
Related:

How to set value of composite variable field using dynamic SQL