Archive
Perl – Writing to file outputting in UTF-16 instead of UTF-8
Recently I needed to write a perl script that ran on Cygwin. My default setting means that any files written by perl were being written in UTF-16. This led to what appeared to be a lot of Japanese writing, making it completely illegible and unusable.
After a lot of digging around on the internet, I managed to hack together the following code:
open my $SH, ">>:raw:encoding(UTF16-LE):crlf:utf8", "test1.txt";;
print $SH "\x{FEFF}";
print "Some test writing \n";
close ($SH);
This code tells perl we’re going to pass “characters” to this file handle instead of bytes. Next transform \n into \r\n to give DOS line endings. Next apply the UTF16-LE, so that 0x0A becomes 0x0A 0x00. This stops perl writing a byte order mark (BOM) at the beginning of the file. Finally, the raw:encoding removes the default ctrf so that it is not in the wrong place.
Now the file is being opened with the correct coding, we need to write the BOM to the beginning of the file to tell readers of this file what endianness it is. We do this by printing \x{FFF} to the file.
Perl – Oracle SQL – pass sql output into a perl variable
It is possible to run a sql command to retrieve results to an array without using the DBI or DBD modules of perl.
The following script (kr.pl) connects to sqlplus, runs a pre-written sql file to get the owner and table_name from dba_tables, puts this into an array in perl, then perl processes the array into a hash of has arrays, finally printing out a list of tables and owners. This is just an example of how perl can be used along with sqlplus to retrieve data from the database. We could take the perl script further and manipulate the data within the hash of hash array, but that is beyond the scope of this post.
#!/usr/bin/perl
@test = `sqlplus -S \/ as sysdba \@kr.sql`;
my $count = 0;
foreach my $value (@test){
my ($table_name, $owner) = split(/#/,$value);
$count++;
if (! defined %testarray) {
%testarray = ($count => {table_name=> $table_name, owner=> $owner,},);
}
else {
@testarray{$count} = {'table_name' => $table_name, 'owner' => $owner};
}
}
foreach my $table (keys %testarray) {
for my $number (keys %{ $testarray{$table}}) {
print "$number=$testarray{$table}{$number}";
}
print "\n ";
}
The sql code (kr.sql) is as follows:
set feedback off pages 0 timing off echo off
set feedback off pages 0 timing off echo off
set feedback off pages 0 timing off echo off
select table_name||'#'|| owner from dba_tables where owner = 'SYS' and table_name like '%JAVA%';
exit
~
The output of the perl script is as follows:
/home/krobbe > ./kr.pl
owner=SYS
table_name=PROCEDUREJAVA$
owner=SYS
table_name=JAVA$RMJVM$AUX2
owner=SYS
table_name=JAVA$JVM$STEPS$DONE
owner=SYS
table_name=JAVA$JVM$STATUS
owner=SYS
table_name=WRH$_JAVA_POOL_ADVICE
owner=SYS
table_name=TRIGGERJAVAF$
owner=SYS
table_name=JAVA$RMJVM$AUX
owner=SYS
table_name=JAVA$POLICY$
owner=SYS
table_name=JAVAOBJ$
owner=SYS
table_name=TRIGGERJAVAC$
owner=SYS
table_name=TRIGGERJAVAM$
owner=SYS
table_name=TRIGGERJAVAS$
owner=SYS
table_name=JAVA$RMJVM$AUX3
owner=SYS
table_name=JAVA$POLICY$SHARED$TABLE
owner=SYS
table_name=JAVASNM$
owner=SYS
table_name=JAVA$PREFS$
Perl – Get current time without perl packages
Although perl has a built in package for getting the DateTime, you cannot guarantee that the system you are using has this package installed. Therefore in this situation it would be necessary to put the localtime into an array and work with it from there. The below script shows how to do this:
### initialize datetime my %DTTIME = ();
my ($SEC,$MIN,$HOUR,$MDAY,$MON,$YEAR,$WDAY,$YDAY,$ISDST) = localtime(time);
### format numbers
$DTTIME{year } = sprintf "%04d",($YEAR + 1900);## 4 digits to specify the year
$DTTIME{mon } = sprintf "%02d",($MON + 1); ## zeropad months
$DTTIME{mday } = sprintf "%02d",$MDAY; ## zeropad day of the month
$DTTIME{wday } = sprintf "%02d",$WDAY + 1; ## zeropad day of week;sunday = 1;
$DTTIME{yday } = sprintf "%02d",$YDAY; ## zeropad nth day of the year
$DTTIME{hour } = sprintf "%02d",$HOUR; ## zeropad hour
$DTTIME{min } = sprintf "%02d",$MIN; ## zeropad minutes
$DTTIME{sec } = sprintf "%02d",$SEC; ## zeropad seconds
$DTTIME{isdst} = $ISDST;
If you wished to then use this you could do so as follows:
print "Date = $DTTIME{mday} - $DTTIME{mon} - $DTTIME{year}";
Perl – Perl Version
Sometimes it is necessary to find which version of perl you are running on your Linux server.
Find Perl Version
$ perl -v