squawk マニュアル

最終更新日: 2007年 6月 11日


目次

I. squawkリファレンスマニュアル
squawk - SQLテキスト処理ツール

例目次

1. ユーザ名の一覧作成
2. 行番号付加
3. 行数カウント
4. echoのエミュレーション
5. printenvのエミュレーション
6. Solarisの"showrev -p"出力の整形

squawkリファレンスマニュアル


目次

squawk - SQLテキスト処理ツール

名前

squawk — SQLテキスト処理ツール

概要

squawk [-c sql] [-i] [-n] [-encoding encoding] [-header] [-F separator] [-csv] [-csv-in] [-csv-out] [-tmpfile] [-version] [-help] [--] [scriptfile] [scriptoption...] [--] [inputfile...]

解説

squawkは、 awk(1)のように ファイルを一行ずつ読み取り、蓄積したデータをSQL言語を使って 処理するツールです。

SQLエンジンとしてSQLiteを 使用しています。SQLiteはSQL92にほぼ準拠していますので、SQL92の ほとんどの機能を利用できます。

SQL文は-cオプションまたは scriptfileで 指定します。 squawkinputfileを指定していれば そのファイルを、指定していない場合は標準入力を INPUTテーブルに 読み込んでから指定されたSQL文を実行し、SELECT文の 結果を標準出力に出力します。

scriptfileinputfileの 両方を省略するか、-iを 指定した場合には対話的に起動します。対話モードでは標準入力からSQL文を 読み取り、実行結果を標準出力に出力します。

scriptoptionにはNAME=VALUEの 形式でパラメータを指定します。指定されたパラメータは PARAMETERS テーブルに格納されます。 '='文字は必須です。'='文字が含まれていない引数は inputfileとして解釈されます。

squawkは指定されたファイル全てを一度読み込んでから 処理するため、単純な処理では awk(1)等に比べて処理が重くなります。 しかし、SQLのGROUP BYORDER BYなどの 機能を使用したいときや索引を使用した検索を繰り返す場合には強力な ツールとなることでしょう。

squawkの最新版は sourceforgeで、 最新のマニュアルは ここで 入手できます。

オプション

squawkでは以下のオプションを受け付けます。

-c sql

実行するSQLを指定します。通常SQLには空白が必要ですので、 sh(1)などから起動する場合は SQL全体を'で括る必要があります。

sqlには;で区切って複数のSQL文を記述することが できます。一番最後のSQL文の末尾の;は省略可能です。

-cを指定した場合は scriptfileは指定できません。ファイル名を 指定するとinputfileとして解釈されます。

-i

対話形式で起動します。inputfileを指定しつつ 対話形式で起動したいときに使用します。

-iを指定した場合は scriptfileは指定できません。ファイル名を 指定するとinputfileとして解釈されます。

-n

inputfileの読み込みを行いません。 inputfile引数の指定をしたとしてもエラーには なりません。指定された引数は ARGVテーブルで 参照することができます。

スクリプト内で set noinputコマンドを 実行することでも同じ効果が得られます。

-encoding encoding

入出力時のエンコーディングを指定します。 多言語対応機能については多言語対応項を参照してください。 スクリプト内で set encodingコマンドを 実行することでも同じ効果が得られます。

-header

SELECT文を実行したときにデータの前にカラム名の 一覧を出力します。 スクリプト内で set headingコマンドを 実行することでも同じ効果が得られます。

-F separator

入力フィールドの区切り文字を指定します。 区切り文字についての詳細はフィールド分割項を 参照してください。 -Fオプションに限り、-Fseparatorの間の空白を省略することができます。 スクリプト内で set fsコマンドを 実行することでも同じ効果が得られます。

-csv

入力および出力をCSVフォーマットで処理します。

スクリプト内で set csvコマンドを 実行することでも同じ効果が得られます。

-csv-in

入力をCSVフォーマットで処理します。

スクリプト内で set csvinputコマンドを 実行することでも同じ効果が得られます。

-csv-out

出力をCSVフォーマットで処理します。

スクリプト内で set csvoutputコマンドを 実行することでも同じ効果が得られます。

-tmpfile

ファイルから入力したデータを蓄積する領域を、メモリ上ではなく 一時ファイル上に確保します。データ量が非常に多い場合に有効です。

-version

squawkのバージョンと、組み込まれている SQLiteエンジンのバージョンを表示します。

-help

squawkの使用方法を簡潔に表示します。

起動と実行

squawkを起動すると、まず組み込みテーブル PARAMETERSARGVENVIRONSERIESDUALが作成されます。 組み込みテーブルの作成が完了すると、SQLスクリプトの読み込みが始まります。 -nオプションまたは set noinputコマンドが 指定されていなければ、最初のSQLコマンドを読み取ったとき(または executeコマンドを実行したとき)に INPUTテーブルを作成し、 inputfile引数で指定されたファイルから データを読み取ってテーブルに格納します。

スクリプトファイルの最初の一行目が#で始まっている場合、その行は コメントとみなして無視します。この機能により、Unix等の環境では 先頭行に"#!/usr/bin/squawk"等の行を挿入することでスクリプトを 直接実行できるようになります。

UPDATE文やCREATE文などはメモリ上 (-tmpfileオプションが 指定されていれば一時ファイル上)のデータベースへの更新のみが行われ、 何も出力はありません。 SELECT文を実行すると、結果が標準出力に出力されます。 各式は空白文字 (set ofsコマンドで変更可能) で区切られ、各行の末尾に改行文字 (set orsコマンドで変更可能) が付加されます。 set headingコマンドで onを指定すると、データの前にカラム名を出力します。

SQLの構文や型などについての詳細は SQLiteのマニュアルを 参照してください。 このマニュアルでは主にsquawkで拡張された機能に ついて記述します。

ファイルの読み込み

レコード分割

inputfileで指定されたファイルや inputコマンドで 指定されたファイルは、通常改行文字によってそれぞれのレコードに 分割されINPUTテーブル (inputコマンドの 場合は指定されたテーブル)の各レコードに格納されます。レコードの区切りは set rsコマンドで 変更できます。区切り文字が単一文字の場合にはその文字自身が区切り文字と して扱われますが、二文字以上の文字列の場合には正規表現として扱われます。 特殊な場合として、区切り文字に空文字列を指定すると空行(連続した改行)が レコードの区切りとなります。区切り文字として空文字列を指定すると、 set fsコマンドで指定された フィールドセパレータの他に、改行によっても区切られるようになります。

ここでの改行文字はLF文字を指します。DOSの改行(CRLF)を区切りとしたい 場合にはset rsコマンドで 明示的に"\r\n"や"\r?\n"などと指定してください。

フィールド分割

読み取ったレコードはさらにフィールド区切りによって各フィールドに分割され、 $1$2などのカラムに格納されます。 フィールドはデフォルトでは連続する空白/タブ/改行文字によって分割されます。 フィールド区切りは set fsコマンドで 変更できますが、指定した文字列の形式によって以下のように動作が変わります。

単一の空白文字の場合

連続する空白/タブ/改行文字によって分割されます(デフォルトと同じ動作です)。

空白以外の単一の文字の場合

指定した文字によって分割されます。

二文字以上の文字列の場合

指定した文字列が正規表現として扱われます。

空文字列の場合

各文字がそれぞれのフィールドとして分割されます。

INPUTテーブルのフィールドは初期状態で9つ (set minnfコマンドで 変更可)用意されていますが、フィールド分割の結果9つ以上のフィールドに 分割された場合、INPUTテーブルのカラムが自動的に拡張されます。

分割の結果テーブルに用意されているカラム数よりもフィールド数が 少なかった場合、残りのカラムにはNULLが格納されます。 squawkでは空文字列とNULLが 区別される点に注意してください。

GNU awkでサポートされている固定長サイズ(FIELDWIDTHS)によるフィールド分割 機能は(squawkの現在のバージョンでは)サポートされていません。

CSVモード

set csvコマンドなどを 指定することで、CSVファイルを処理することもできます。 CSV入力モードの場合には常にレコード区切りは改行文字、フィールド区切りは ,(カンマ)になります。 set fsコマンドや set rsコマンドを 指定するとCSV入力モードは解除されます。

組込みテーブル

squawkには以下のテーブルが組み込みのテーブルとして 用意されています。 組み込みのテーブルはいずれも起動時に自動的に用意されるというだけの ものであり、他のテーブルと同様に更新(INSERT/ UPDATE/DELETE)したり、 削除(DROP TABLE)したりすることもできます。

PARAMETERS
  NAME TEXT PRIMARY KEY,    -- NAME of NAME=VALUE argument
  VALUE TEXT                -- VALUE of NAME=VALUE argument

scriptoptionで指定されたパラメータが格納されます。

ARGV
  IND INTEGER PRIMARY KEY,  -- index of argument
  ARG TEXT                  -- argument text

inputfileで指定されたパラメータが格納されます。 INDには1から順に番号が振られます。 このテーブルは-nオプションや set noinputの指定の 有無に関係なく設定されます。

ENVIRON
  NAME TEXT PRIMARY KEY,    -- environment name
  VALUE TEXT                -- environment value

squawkが起動されたときの全ての環境変数が格納されます。 このテーブルを更新したとしても、 hostコマンドと system関数の動作には 影響しません。

SERIES
  VALUE INTEGER PRIMARY KEY -- sequencial value

INTEGERの下限から上限まで、全ての整数が格納されています。 このテーブルは読み取り専用で、更新はできません。 通常はBETWEENなどを指定したWHERE句で 検索範囲を限定して利用します。

DUAL
  DUMMY TEXT                -- dummy text

Oracleとの互換性のため、'X'という文字列のレコードが一行だけ格納されています。

SELECT 'message' FROM DUAL;

といった使いかたができますが、squawkでは FROM句を省略できるため

SELECT 'message';

としても同じように動作します。

INPUT
  NR INTEGER PRIMARY KEY,  -- total index number of records
  FNR INTEGER,             -- index number of records in each file
  FILENAME TEXT,           -- filename
  FN INTEGER,              -- index number of files
  NF INTEGER,              -- number of fields
  RT TEXT,                 -- record terminator
  $0 TEXT,                 -- whole record
  $1 TEXT,                 -- 1st field
  $2 TEXT,                 -- 2nd field
  ...

入力ファイルから読み取ったレコードが格納されます。

NRには入力全体での行番号が、 FNRには各ファイルごとの行番号が格納されます。 FILENAMEにはファイル名が格納されます。 同じファイルを二回以上指定した場合FILENAMEでは 区別できないため、各ファイルにFNで1から順に番号が振られます。 NFは各レコードのフィールド数です。 RTにはレコードの区切りとなった文字列が格納されます。 $0はレコード区切り文字の部分を除外したレコード全体が 格納されます。 $1以降にはフィールド区切り文字の部分を除外した 各フィールドの内容が格納されます。

各フィールド用のカラムは初期状態で$1から$9までの9つ (set minnfコマンドで 変更可)が用意されていますが、フィールド分割の結果9つ以上のフィールドに 分割された場合には必要な分だけ自動的に拡張されます。

squawkコマンド

squawkではSQL文の他に以下のコマンドを使用できます。

squawkコマンドは一行に一つのコマンドを記述します。 コマンドの引数は空白かタブ文字で区切られます。 文字列の引数に空白を含めたいときには、引数を'または"で 括ってください。"で括った場合、\文字はエスケープ文字として 解釈され、\nは改行文字(LF)に、\tはタブ文字に、\rは復帰文字(CR)に、 \\と\"と\'はそれぞれ\と"と'に、\nnn(nnnは八進数)はASCIIコードnnnの 文字に変換されます。 'で括った場合にはこの変換は行われません。 SQL文と同様に、文字列以外の部分では大文字と小文字は区別されません。

host COMMAND [ARG...]

! COMMAND [ARG...]

OSコマンドを実行します。

help

?

コマンドヘルプを出力します。

@ SCRIPTFILE

引数で指定されたスクリプトファイルを読み込んで実行します。

exit

quit

squawkを終了します。 @コマンドで 読み込んだスクリプト内で実行した場合でも、即座に squawkの実行を終了させます。

exec[ute] EXPR

SQL式EXPRによって動的に生成されたSQL文を実行します。

input TABLE FILE...

TABLEで指定された名前でテーブルを作成し、 ファイルFILEからデータを読み取って格納します。 作成されるテーブルの構造や格納されるデータの内容は INPUTテーブルと 同じです。

spool FILE [rep [lace]]

spool FILE app [end]

spool off

spool [std [out]]

SELECT文の実行結果の出力先をFILEに 変更します。 replaceを指定すると既にファイルがある場合に データを上書きします。この動作がデフォルトです。 appendを指定すると既にファイルがある場合に データを追記します。 offを指定すると出力を止めます。 stdoutを指定すると出力先を標準出力に切り替えます。

set

各種setコマンドで設定されている値の一覧を出力します。

set enc [oding] ENCODING

入出力とスクリプトの読み込みに使用するエンコーディングを全て 指定されたエンコーディングに変更します。 -encodingオプションでも 同じ効果が得られます。

set { inputencoding | ienc } ENCODING

ファイル入力に使用するエンコーディングを指定されたエンコーディングに変更します。 INPUTテーブルを 作成するときのエンコーディングを指定するには、最初のSQL文より前に set iencコマンドを実行する必要があります。

set { outputencoding | oenc } ENCODING

出力に使用するエンコーディングを指定されたエンコーディングに変更します。

set { scriptencoding | senc } ENCODING

スクリプトの読み込みに使用するエンコーディングを 指定されたエンコーディングに変更します。 squawkの現在のバージョンではscriptencodingは squawk全体の属性となっているため、 @コマンドで 読み込んだスクリプトの内部でscriptencodingを 変更した場合、元のスクリプトに戻ってもscriptencodingは 変更されたままになります。

set { ignorecase | ic } { on | off }

onを指定すると、 レコードフィールドの分割の際に 区切り文字の大文字と小文字を区別しません。 レコードとフィールドの分割以外の機能には(squawkの現在の バージョンでは)影響しません。

set noinput

INPUTテーブルの 作成を抑止します。 このコマンドはスクリプトの最初のSQL文よりも前に実行しなければ 効果がありません。 -nオプションでも 同じ効果が得られます。

set minnf N

INPUTテーブルの フィールド用カラム数の初期値を設定します。 スクリプトで10個目のフィールド($10)を利用したいが、入力ファイルに 必ずしも10以上のフィールドがあるとは限らない、というような場合に set minnf 10と指定することで 「カラムが存在しません」というSQLエラーを避けることができます。

set { hea [ding] | header [s] } { on | off }

onを指定すると、 SELECT文を実行したときにデータの前にカラム名の 一覧を出力します。 -headerオプションでも 同じ効果が得られます。

set prompt MAIN CONT

対話形式で起動しているときに、プロンプトを変更します。

set csv

入力と出力の両方をCSVモードに変更します。 -csvオプションでも 同じ効果が得られます。

set csvin [put]

入力のみをCSVモードに変更します。出力形式は変更されません。

set csvout [put]

出力のみをCSVモードに変更します。入力形式は変更されません。

set fs TEXT

入力のフィールド区切り文字を変更します。 入力がCSVモードだった場合、 CVSモードは解除されます。

set { ofs | colsep | separator } TEXT

出力のフィールド区切り文字を変更します。デフォルトは空白文字です。 出力がCVSモードだった場合、CVSモードは解除されます。

出力の文字幅を固定にしたい場合など、出力形式を細かく調整するには sprintf関数を 使用してください。

set ors TEXT

出力のレコード区切り文字を変更します。デフォルトは改行文字(LF)です。 DOSの改行を区切りとしたい場合はset ors "\r\n"と してください。

set rs TEXT

入力のレコード区切り文字を変更します。 デフォルトは改行文字(LF)です。 入力がCSVモードだった場合、 CVSモードは解除されます。

set { ofmt | numf | numformat } TEXT

SELECTの結果がREAL型だった場合、 TEXTで指定された書式で出力します。 デフォルトは"%.6g"です。

set null [value] TEXT

SELECTの結果がNULLだった場合、 TEXTで指定された文字列に置き換えられます。 デフォルトは空文字列です。

組込み関数

squawkには SQLiteの標準の関数を含め、 以下の関数が用意されています。

数学関数

number abs( number x)

xの絶対値を返します。

real acos( real x)

xの逆余弦を返します。

real asin( real x)

xの逆正弦を返します。

real atan( real x[, real y])

x/y( yが省略された場合x)の逆正接を返します。

real atan2( real x, real y)

x/yの逆正接を返します。

real atanh( real x)

xの逆双曲線正接を返します。

real atn2( real x, real y)

x/yの逆正接を返します。

real cbrt( real x)

xの実数立方根を返します。

real ceil( real x)

x以上で xに最も近い整数を返します。

real ceiling( real x)

x以上で xに最も近い整数を返します。

real cos( real x)

xの余弦を返します。

real cosh( real x)

xの双曲線余弦を返します。

real degrees( real x)

xをラジアンから度に変換します。

real exp( real x)

e(自然対数の底)のx乗を返します。

real floor( real x)

x以下で xに最も近い整数を返します。

integer int( any x)

xを整数に変換します。 xが文字列の場合、xの先頭の 数字の部分が10進数の数字として解釈されます。

real ln( real x)

xの自然対数を返します。

real log([ real x,] real y)

xを底としたyの対数を返します。 xが省略された場合、yの 自然対数を返します。

real log10( real x)

xの常用対数を返します。

real log2( real x)

2を底としたxの対数を返します。

real mod( real x, real y)

xyで割った余りを返します。 剰余演算の詳細はfmod(3)を参照してください。

real pi()

円周率(3.1415...)を返します。

real pow( real x, real y)

xy乗を返します。

real power( real x, real y)

xy乗を返します。

real radians( real x)

xを度からラジアンに変換します。

integer random()

-(2^64-1)から2^64-1の間の乱数を返します。

real round( real x[, integer n])

xを小数点以下n桁目で 四捨五入します。 nを省略すると小数点以下を四捨五入します。

integer sign( real x)

xが0より大きい場合1を、 0より小さい場合-1を、0の場合0を返します。

real sin( real x)

xの正弦を返します。

real sinh( real x)

xの双曲線正弦を返します。

real sqrt( real x)

xの正の平方根を返します。

real tan( real x)

xの正接を返します。

real tanh( real x)

xの双曲線正接を返します。

real trunc( real x[, integer n])

xを小数点以下n桁目で 切り捨てます。 nを省略すると小数点以下を切り捨てます。

real truncate( real x[, integer n])

xを小数点以下n桁目で 切り捨てます。 nを省略すると小数点以下を切り捨てます。

文字列関数

integer ascii( text s)

sの最初の1文字の文字コードをUnicodeで返します。

text btrim( text s[, text chars])

sの先頭と末尾からchars( デフォルトは空白文字)に含まれる文字を除外した文字列を返します。

integer char_length( text|blob s)

sの文字数を返します。 ただし、sの型がBLOBの場合には sのバイト数を返します。

integer character_length( text|blob s)

sの文字数を返します。 ただし、sの型がBLOBの場合には sのバイト数を返します。

text chr([ integer c, ...])

指定されたUnicodeの文字コードで構成された文字列を返します。

blob|text concat( blob|text s, ...])

指定された文字列全てを連結した文字列を返します。 ただし、sが全てBLOBまたは NULLの場合には、全てのBLOBを 連結したBLOBを返します。 sNULLの場合には 空文字列(または空のBLOB)を連結します。

blob|text convert( blob|text s, text tocode[, text fromcode])

sの文字エンコーディングを fromcodeからtocodeへ変換します。 fromcodeを指定した場合には sBLOBとして解釈され、 fromcodeを省略した場合には sTEXTとして解釈されます。 同様に、tocodeを指定した場合には BLOB型のデータを返し、 tocodeNULLを指定した場合には TEXT型のデータを返します。

integer crc32( blob s)

sのCRC32の値を返します。

blob decode( text s, text type)

stypeの方式で デコードして返します。typeには 'base64'または'hex'を指定できます。

text encode( blob s, text type)

stypeの方式で エンコードして返します。typeには 'base64'または'hex'を指定できます。

text s1 [not] glob text s2

s1s2に マッチする場合真(1)を、マッチしない場合偽(0)を返します。 notを指定した場合には結果の真偽が逆になります。 s2にはglob(3)のファイルマッチパターンが指定できます。 globマッチでは大文字と小文字は区別されます。

text hex( blob s)

sを16進エンコードして返します。

integer index( text s, text sub)

sの中でsubと一致する 部分の位置を返します。

text initcap( text s)

sの中で単語の最初の文字を大文字に、 それ以外の部分を小文字に変換します。 アルファベットと数字が並んでいる部分が単語として解釈されます。

integer instr( text s, text sub[, integer pos[, integer occ]])

sの中でsubと一致する 部分の位置を返します。 possの中で検索を開始する 位置(最初の文字が1、負の場合は右から数えた位置)を指定します。 occsubと一致した部分のうち 何番目に一致した位置を返すかを指定します。

以下に例を示します。

squawk> select instr('abcdabcdabcd', 'bc');
2
squawk> select instr('abcdabcdabcd', 'bc', 3);
6
squawk> select instr('abcdabcdabcd', 'bc', 1, 3);
10

text lcase( text s)

sの大文字の部分を全て小文字に変換します。

integer length( text|blob s)

sの文字数を返します。 ただし、sの型がBLOBの場合には sのバイト数を返します。

text s1 [not] like text s2 [escape text e]

s1s2に マッチする場合真(1)を、マッチしない場合偽(0)を返します。 notを指定した場合には結果の真偽が逆になります。 s2には任意の一文字にマッチする'_'および 任意の0文字以上の文字列にマッチする'%'を含めることができます。 eにはエスケープ文字を指定します。 エスケープ文字に続く任意の文字は、('%'と'_'の場合も含め) その文字自身にマッチします。 likeマッチでは大文字と小文字は区別されません。

blob load_file( text fname)

fnameで指定されたファイルの内容を返します。

integer locate( text sub, text s[, integer pos])

sの中でsubと一致する 部分の位置を返します。 possの中で検索を開始する 位置(最初の文字が1、負の場合は右から数えた位置)を指定します。

以下に例を示します。

squawk> select locate('bc', 'abcdabcdabcd');
2
squawk> select locate('bc', 'abcdabcdabcd', 3);
6

text lower( text s)

sの大文字の部分を全て小文字に変換します。

text lpad( text s, integer len[, text p])

sの先頭部分にp (デフォルトは空白文字)を詰めて文字列の長さを lenにします。 sの長さがlenよりも 長い場合は文字列を切り詰めます。

以下に例を示します。

squawk> select 'X' || lpad('ab', 3);
X ab
squawk> select 'X' || lpad('de', 5, 'Y');
XYYYde
squawk> select 'X' || lpad('abcd', 2);
Xab

text ltrim( text s[, text chars])

sの先頭からchars( デフォルトは空白文字)に含まれる文字を除外した文字列を返します。

text md5( blob s)

sのMD5ハッシュの値を16進エンコーディングで返します。

以下に例を示します。

squawk> select md5('squawk');
e1f0e4eb8a870c6ae8a9cb330559df07

text nl2br( text s)

sの中の改行文字の直前に'<br>'を挿入します。

integer octet_length( blob s)

sのバイト数を返します。 sTEXT型の値が 渡された場合、UTF-8でのバイト数が返ります。

integer ord( text s)

sの最初の1文字の文字コードをUnicodeで返します。

integer posstr( text s, text sub)

sの中でsubと一致する 部分の位置を返します。

text|integer|real quote( any v)

引数の型がTEXT,BLOB,NULLの いずれかの場合、SQL文にそのまま利用できるようにした文字列を返します。

引数の型がINTEGER,REALの場合には 引数をそのまま返します。

以下に例を示します。

squawk> select 'SELECT ' || quote('ab''c ') || ' FROM DUAL;';
SELECT 'ab''c ' FROM DUAL;
squawk> select quote(X'001122');
X'001122'
squawk> select quote(null);
NULL

blob randomblob( integer n)

長さnのランダムなBLOBを生成します。

text repeat( text s, integer n)

sn回繰り返した文字列を返します。

text replace( text s, text sub[, text r])

sのうちsubに一致する部分を r(デフォルトは空文字列)に置き換えます。

text rpad( text s, integer len[, text p])

sの末尾にp (デフォルトは空白文字)を詰めて文字列の長さを lenにします。 sの長さがlenよりも 長い場合は文字列を切り詰めます。

以下に例を示します。

squawk> select rpad('ab', 3) || 'X';
ab X
squawk> select rpad('de', 5, 'Y') || 'X';
deYYYX
squawk> select rpad('abcd', 2) || 'X';
abX

text rtrim( text s[, text chars])

sの末尾からchars( デフォルトは空白文字)に含まれる文字を除外した文字列を返します。

text sha( blob s)

sのSHA1ハッシュの値を16進エンコーディングで返します。

以下に例を示します。

squawk> select sha('squawk');
fb3ac2a2d79be31e635202528b8d6b32f2c5d448

text sha1( blob s)

sのSHA1ハッシュの値を16進エンコーディングで返します。

以下に例を示します。

squawk> select sha1('squawk');
fb3ac2a2d79be31e635202528b8d6b32f2c5d448

text space( integer n)

空白文字をn回繰り返した文字列を返します。

integer split_part( text s[, text d], integer n)

sdと一致する部分で分割し、 n番目の部分文字列を返します。

以下に例を示します。

squawk> select split_part('a bc  d', 2);
bc
squawk> select split_part('a bc  d', 4);
d
squawk> select split_part('a bc  d', 'b', 2);
c  d

text sprintf( text fmt[, any arg, ...])

fmtの書式に従って編集した文字列を返します。 '%'が書式指定子として解釈されます。'\'はエスケープ文字として 解釈されないことに注意してください。

sprintfの書式は printf(3)とほぼ同様です。 引数の位置を指定するための'%m$'および'*m$'指定を受け付けます。 長さ指定子('h'や'l'など)は受け付けません。 フラグ文字として、以下の文字を受け付けます。

-

変換結果を左揃えにします。0指定より優先されます。

+

数値変換で引数が負でない場合に数字の前に+符号を付加します。 空白文字指定より優先されます。

' '

(空白文字)数値変換で引数が負でない場合に数字の前に空白文字を付加します。

#

o変換では引数が0でない場合に数字の前に0を付加します。 x変換では引数が0でない場合に数字の前に0xを付加します。 X変換では引数が0でない場合に数字の前に0Xを付加します。 e,E,f,g,G変換では引数が整数の場合であっても小数点を省略しません。 g,G変換では小数点以下の末尾の0を省略しなくなります。

0

数値変換でフィールド幅が指定された場合、空白の代わりに0を埋めます。

変換指定子として、以下の文字を受け付けます。

c

引数がINTEGER型またはREAL型の 場合、指定したUnicodeの文字一文字を出力します。 その他の場合、引数はTEXT型として解釈され、最初の 一文字を出力します。

d, i

INTEGER型の引数を取り、10進数の数字を出力します。

o

INTEGER型の引数を取り、8進数の数字を出力します。

x, X

INTEGER型の引数を取り、16進数の数字を出力します。 x変換ではa〜fを、X変換ではA〜Fを使います。

f

REAL型の引数を取り、ddd.ddddddといった形式で出力します。

e, E

REAL型の引数を取り、ddd.ddde[+-]ddといった形式で出力します。 E変換ではeの代わりにEを使います。

g, G

REAL型の引数を取り、%fまたは%e変換で出力します。 小数点以下の末尾の0は省略されます。 G変換では%e変換の代わりに%E変換を使います。

s

TEXT型の引数を取ってそのまま出力します。

%

%文字に変換されます。

integer strpos( text s, text sub)

sの中でsubと一致する 部分の位置を返します。

blob|text substr( blob|text s, integer from[, integer to])

sの中でfrom文字目から to文字目(デフォルトは末尾)までを返します。 sBLOBの場合には、文字数ではなく バイト数で区切り、BLOBを返します。

blob|text substring( blob|text s, integer from[, integer to])

sの中でfrom文字目から to文字目(デフォルトは末尾)までを返します。 sBLOBの場合には、文字数ではなく バイト数で区切り、BLOBを返します。

text tolower( text s)

sの大文字の部分を全て小文字に変換します。

text toupper( text s)

sの小文字の部分を全て大文字に変換します。

text trim( text s[, text chars])

sの先頭と末尾からchars( デフォルトは空白文字)に含まれる文字を除外した文字列を返します。

trim([ leading|trailing|both [chars from] s)の 形式は(squawkの現在のバージョンでは)サポートされていません。

text u( text s)

sに含まれるエスケープシーケンスを変換して返します。 以下のエスケープを受け付けます。

\a

警告文字に置き換えられます。

\b

後退文字に置き換えられます。

\f

フォームフィード文字に置き換えられます。

\n

改行文字(LF)に置き換えられます。

\r

復帰文字(CR)に置き換えられます。

\t

タブ文字(TAB)に置き換えられます。

\v

垂直タブ文字に置き換えられます。

\'

シングルクォート文字(')に置き換えられます。

\"

ダブルクォート文字(")に置き換えられます。

\\

バックスラッシュ文字(\)に置き換えられます。

\ddd

Unicodeで指定された文字に置き換えられます。 dddは1〜3桁の8進数字です。 377より大きい数字は指定できません。

\xXXX

Unicodeで指定された文字に置き換えられます。 XXXは任意の桁数の16進数字です。

\unnnn

Unicodeで指定された文字に置き換えられます。 nnnnは16進数字4桁です。

\Unnnnnnnn

Unicodeで指定された文字に置き換えられます。 nnnnnnnnは16進数字8桁です。

text ucase( text s)

sの小文字の部分を全て大文字に変換します。

text upper( text s)

sの小文字の部分を全て大文字に変換します。

text uuid([ text type])

UUIDを生成して'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'の形式で返します。 typeに'random'を指定すると乱数を元に 生成します。デフォルトではOSが乱数デバイスをサポートしていない場合、 ハードウェア情報を元にUUIDを生成しようとします。

integer width( text s)

sの表示上の幅を返します。

以下に例を示します。

squawk> select width('abc');
3
squawk> select width('漢字');
4

正規表現関数

text gsub( text t, text r[, text s[, integer pos[, integer occ[, text flags]]]])

tの中で正規表現 rにマッチする部分を s(デフォルトは空文字列)に置き換えた結果の文字列を 返します。 postの中で検索を開始する 位置(最初の文字が1、負の場合は右から数えた位置)を指定します。 occrにマッチした部分のうち どのマッチを置き換えるか(0の場合は全て置き換え、負の場合は指定した数までの 全てを置き換え)を指定します。 flagsは正規表現の動作を指定する文字列です。 flagsに'b'が含まれる場合、rは 基本正規表現として、'e'が含まれる場合には拡張正規表現として解釈されます (デフォルトは拡張正規表現)。 flagsに'i'が含まれる場合、マッチの際に 大文字小文字の差を無視し、'c'が含まれる場合は無視しません (デフォルトは無視しない)。 flagsに'm'が含まれる場合、マッチの際に 改行文字を特別に扱い、'n'が含まれる場合は通常の文字と同様に扱います。 (デフォルトは通常の文字と同様に扱う)。

以下に例を示します。

squawk> select gsub('abcabcabc', 'b.', 'x');
axaxax
squawk> select gsub('abcabcabc', 'b.', 'x', 3);
abcaxax
squawk> select gsub('abcabcabc', 'b.', 'x', -8);
axaxax
squawk> select gsub('abcabcabc', 'b.', 'x', 1, 2);
abcaxabc
squawk> select gsub('abcabcabc', 'b.', 'x', 1, -2);
axaxabc
squawk> select gsub('abcabcABC', 'b.', 'x', 1, 0, 'i');
axaxAx

gsubのパラメータの順序はawkと 異なることに注意してください。 また、flagsの'n'と'm'の意味はOracleと異なります。

text match( text s, text r[, text flags])

sの中で正規表現 rに最初にマッチする部分の開始位置と マッチした部分の長さを空白区切りの文字列で返します。 rに'(...)'が含まれる場合、部分正規表現が マッチする部分の開始位置と長さを末尾に付加して返します。 マッチする部分が無かった場合は'0'を返します。 flagsは正規表現の動作を指定する文字列です。 flagsの指定方法は gsub関数を 参照してください。

以下に例を示します。

squawk> select match('abcdeabcde', 'cde.*x*b');
3 5
squawk> select match('abcdeabcde', 'cd((e)(.*)((q)|x*))b');
3 5 5 2 5 1 6 1 7 0 0 0
squawk> select match('abcdeabcde', 'z');
0

二番目の例では、最初の'3 5'は正規表現全体のマッチする部分、 続く'5 2'は部分正規表現'((e)(.*)((q)|x*))'のマッチする部分を指しています。 マッチする部分が無い部分正規表現'(q)'に対しては'0 0'が返ります。

text s1 [not] regexp text s2

s1が拡張正規表現s2に マッチする場合真(1)を、マッチしない場合偽(0)を返します。 notを指定した場合には結果の真偽が逆になります。 regexpマッチでは大文字と小文字は区別されます。

integer regexp_like( text s, text r[, text flags])

sが正規表現rに マッチする場合真(1)を、マッチしない場合偽(0)を返します。 flagsは正規表現の動作を指定する文字列です。 flagsの指定方法は gsub関数を 参照してください。

text regexp_replace( text t, text r[, text s[, integer pos[, integer occ[, text flags]]]])

tの中で正規表現 rにマッチする部分を s(デフォルトは空文字列)に置き換えた結果の文字列を 返します。 postの中で検索を開始する 位置(最初の文字が1、負の場合は右から数えた位置)を指定します。 occrにマッチした部分のうち どのマッチを置き換えるか(0の場合は全て置き換え、負の場合は指定した数までの 全てを置き換え)を指定します。 flagsは正規表現の動作を指定する文字列です。 flagsの指定方法は gsub関数を 参照してください。

以下に例を示します。

squawk> select regexp_replace('abcabcabc', 'b.', 'x');
axaxax
squawk> select regexp_replace('abcabcabc', 'b.', 'x', 3);
abcaxax
squawk> select regexp_replace('abcabcabc', 'b.', 'x', -8);
axaxax
squawk> select regexp_replace('abcabcabc', 'b.', 'x', 1, 2);
abcaxabc
squawk> select regexp_replace('abcabcabc', 'b.', 'x', 1, -2);
axaxabc
squawk> select regexp_replace('abcabcABC', 'b.', 'x', 1, 0, 'i');
axaxAx

flagsの'n'と'm'の意味はOracleと異なることに 注意してください。

integer split( text s[, text r], integer n[, text flags])

sを正規表現r (デフォルトは空白文字一文字)にマッチする部分で分割し、 n番目の部分文字列を返します。 flagsは正規表現の動作を指定する文字列です。 flagsの指定方法は gsub関数を 参照してください。 flagsを指定する場合、 rを省略することはできません。

以下に例を示します。

squawk> select split('a bc  d', 2);
bc
squawk> select split('a bc  d', 4);
d
squawk> select split('a bc  d', 'b', 2);
c  d
squawk> select split('a bc  d', 'C', 1, 'i');
a b

日付/時刻関数

text current_date

UTCでの現在の日付を'YYYY-MM-DD'の形式で返します。

text current_time

UTCでの現在の時刻を'HH:MM:SS'(HHは00〜23)の形式で返します。

text current_timestamp

UTCでの現在の時刻を'YYYY-MM-DD HH:MM:SS'(HHは00〜23)の形式で返します。

text date( text time[, text mod, ...])

timemodで指定した 時刻の日付部分を'YYYY-MM-DD'の形式で返します。 timeには以下のいずれかの形式で日付と時刻を指定します。

'YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM'

日付/時刻/タイムゾーンを指定します。 ミリ秒指定(.FFF)、秒指定(:SS.FFF)、タイムゾーン(+/-HH:MM)は省略できます。 日付と時刻の間に文字'T'を含めることもできます。

'DDDD.DD'

日付/時刻をユリウス日で指定します。

'now'

UTCでの現在の時刻を指定します。

modには以下のいずれかの形式で timeに対する補正を指定します。 指定された全ての補正が左から順に適用されます。

'NNN days'

指定された日数を追加します。'days'の代わりに'day'を使うこともできます。

'NNN hours'

指定された時を追加します。'hours'の代わりに'hour'を使うこともできます。

'NNN minutes'

指定された分を追加します。'minutes'の代わりに'minute'を使うこともできます。

'NNN.NNNN seconds'

指定された秒を追加します。'seconds'の代わりに'second'を使うこともできます。

'NNN months'

指定された月を追加します。'months'の代わりに'month'を使うこともできます。

'NNN years'

指定された年を追加します。'years'の代わりに'year'を使うこともできます。

'start of month'

その月の一日の00:00:00を指定します。

'start of year'

その年の一月一日の00:00:00を指定します。

'start of day'

その日の00:00:00を指定します。

'weekday N'

指定された曜日に変更します。Nには 0(日曜)から6(土曜)の範囲で曜日を指定します。 現在の曜日が指定された曜日と異なる場合、次の指定された曜日の日に移動します。

'unixepoch'

timeが'DDDD.DD'形式で指定された場合、 指定された数値が1970-01-01 00:00:00(UTC)からの秒数と解釈します。

'localtime'

指定された時刻をUTC時刻と解釈し、ローカル時刻を返します。

'utc'

指定された時刻をローカル時刻と解釈し、UTC時刻を返します。

text datetime( text time[, text mod, ...])

timemodで指定した 時刻を'YYYY-MM-DD HH:MM:SS'(HHは00〜23)の形式で返します。 timemodの指定方法は date関数を 参照してください。

real julianday( text time[, text mod, ...])

timemodで指定した 時刻をユリウス日形式で返します。 timemodの指定方法は date関数を 参照してください。

text strftime( text fmt, text time[, text mod, ...])

timemodで指定した 時刻をfmtで指定した書式にしたがって編集した 文字列を返します。 timemodの指定方法は date関数を 参照してください。

fmtに含まれる書式指定文字列はそれぞれ 以下のように変換されます。

%d

月の中の日に変換されます。

%f

小数点以下3桁まで含めた秒数に変換されます。

%H

時に変換されます。

%j

年内の通算日に変換されます。

%J

ユリウス日に変換されます。

%m

月に変換されます。

%M

分に変換されます。

%s

1970/01/01 00:00:00からの秒数に変換されます。

%S

秒に変換されます。

%w

曜日を示す数字に変換されます。日曜日は0、土曜日は6に変換されます。

%W

年内の週数に変換されます。

%Y

年に変換されます。

%%

%文字に変換されます。

text sysdate

ローカル時間帯での現在の時刻を'YYYY-MM-DD HH:MM:SS'(HHは00〜23)の形式で 返します。

integer systime()

現在の時刻を1970-01-01 00:00:00(GMT)からの秒数で返します。

text systimestamp

現在の時刻を'YYYY-MM-DD HH:MM:SS.FFF +hh:mm' (HHは00〜23、FFFはミリ秒、+hh:mmはタイムゾーン)の形式で返します。

text time( text time[, text mod, ...])

timemodで指定した 時刻を'HH:MM:SS'(HHは00〜23)の形式で返します。 timemodの指定方法は date関数を 参照してください。

その他の関数

case [any e0] when any e1 then any v1 [when any e2 then any v2 ...] [else any ve] end

e0e1に等しい場合 v1を、e2に等しい場合 v2を、どれとも等しくない場合 ve(else句が省略された場合 NULL)を返します。 e0が省略された場合、whenの 後の式が真の場合にthenの後の値を返します。

any cast( any v as type typename)

vの型をtypenameに変更します。

any coalesce( any v[, ...])

NULLでない最初の引数を返します。

any if( integer expr, any v1, any v2)

exprが真の場合v1を返し、 偽の場合にはv2を返します。

any ifnull( any v1, any v2)

v1NULLでない場合 v1を返し、NULLの場合には v2を返します。

any max( any v1, any v2[, any v3, ...])

引数の中の最大値を返します。 引数が1つの場合、集計関数となることに 注意してください。

any min( any v1, any v2[, any v3, ...])

引数の中の最小値を返します。 引数が1つの場合、集計関数となることに 注意してください。

any nullif( any x, any y)

xyが異なる場合は xを、等しい場合はNULLを 返します。

any nvl( any x, any y)

xNULLで無い場合 xを、NULLの場合 yを返します。

any nvl2( any x, any y, any z)

xNULLで無い場合 yを、NULLの場合 zを返します。

text sqlite_version()

SQLiteエンジンのバージョンを文字列で返します。

int system( text cmd)

OS環境でコマンドcmdを実行し、 終了ステータスを返します。 コマンドインタプリタの起動に失敗した場合と コマンドインタプリタが異常終了した場合は-1を返します。

text typeof( any v)

vの型名を返します。

以下に例を示します。

squawk> select typeof(1);
integer
squawk> select typeof(1.0);
real
squawk> select typeof('1');
text
squawk> select typeof(null);
null

text version()

squawkのバージョンを文字列で返します。

集計関数

集計関数では引数の手前にallまたは distinctを指定することができます。 allを指定すると全ての行に対して集計処理を行います。 distinctを指定すると一意な行に対して集計処理を行います。 デフォルトはallです。

real avg( [all|distinct] any v)

vNULLでない行の平均値を返します。

integer count([ [all|distinct] any v])

vNULLでない行の数を返します。 vを省略(または'*'を指定)すると全ての行数を返します。

text implode( [all|distinct] [text sep,] text v)

間にsepを挟んで全てのvを 連結します。sepを省略すると全ての vを直接連結します。

結合順序は指定できません。また、結果の文字列のサイズはメモリサイズの制約を 受けることに注意してください。

any min( [all|distinct] any v)

vの最大値を返します。 値の比較の方法については SQLiteのマニュアルを 参照してください。

any min( [all|distinct] any v)

vの最小値を返します。 値の比較の方法については SQLiteのマニュアルを 参照してください。

number sum( [all|distinct] number v)

vの合計値を返します。 対象となるレコードがすべてNULLの場合には NULLを返します。

real total( [all|distinct] number v)

vの合計値を返します。 sum関数と異なり、 対象となるレコードがすべてNULLの場合に0.0を返します。

ソート順記述子

squawkでは以下の文のようにソート順を指定することができます。

squawk> SELECT $1 FROM INPUT ORDER BY $1 COLLATE NATURALORDER;
1
12.3
12.3a
12.35
112

ASCIINOCASE

Unicodeのコード順ですが、A-Z(0x41-0x5a)とa-z(0x61-0x7a)の範囲内のみ 大文字と小文字の違いを無視します。

BINARY

UTF-8のバイナリ順でソートします。

DICTIONARY

言語設定に合わせてソートします。大文字と小文字の違いを区別しません。 実装上はwcscoll(3)を使用しています。

NATIVE

言語設定に合わせてソートします。大文字と小文字の違いの区別は実装に依存します。 実装上はstrcoll(3)を使用しています。

NATIVENOCASE

言語設定に合わせてソートします。大文字と小文字の違いを区別しません。 実装上はwcscoll(3)を使用しています。

NATURALORDER

自然順でソートします。詳細は http://sourcefrog.net/projects/natsort/を参照してください。 大文字と小文字の違いは区別します。

NATURALNOCASE

自然順でソートします。詳細は http://sourcefrog.net/projects/natsort/を参照してください。 大文字と小文字の違いはASCIIの範囲内のみ無視します。

NOCASE

Unicodeのコード順ですが、大文字と小文字の違いを無視します。

NOCASEASCII

Unicodeのコード順ですが、A-Z(0x41-0x5a)とa-z(0x61-0x7a)の範囲内のみ 大文字と小文字の違いを無視します。

NOCASENATIVE

言語設定に合わせてソートします。大文字と小文字の違いを区別しません。 実装上はwcscoll(3)を使用しています。

NOCASENATURAL

自然順でソートします。詳細は http://sourcefrog.net/projects/natsort/を参照してください。 大文字と小文字の違いはASCIIの範囲内のみ無視します。

NOCASEPOSIX

Unicodeのコード順ですが、A-Z(0x41-0x5a)とa-z(0x61-0x7a)の範囲内のみ 大文字と小文字の違いを無視します。

POSIXNOCASE

Unicodeのコード順ですが、A-Z(0x41-0x5a)とa-z(0x61-0x7a)の範囲内のみ 大文字と小文字の違いを無視します。

多言語対応

squawkの多言語対応機能は、大きく分けて 文字種認識機能と文字エンコーディング変換機能に分けられます。

文字種認識機能

squawkでは文字列の大文字・小文字の扱いと ソート順序でいくつかの機能の動作が言語設定に依存します。 具体的には、 tolowerなどの 文字種変換関数と、native などのソート順指定子が影響を受けます。 OSによってはgsub関数や FSに二文字以上指定した場合などの 正規表現機能にも影響することがあります。 なお FSおよび RSに シングルバイト文字一文字を指定し、 IGNORECASEonを指定した場合の動作は(squawkの現在のバージョンでは) 言語に依存せず、"C"ロケールの場合と同じ動作をします。

言語依存動作は環境変数 SQUAWK_LANGで 設定します。 SQUAWK_LANGには 環境変数LANGの 言語/地域設定部分(エンコーディング指定を除いた部分。"en_US"や"ja_JP"など)を 設定します。 SQUAWK_LANGを 省略した場合、squawkは 環境変数LANG等から 適切な言語を推定します。

文字エンコーディング変換

squawkは内部エンコーディングとしてUTF-8を使用しますが、 入出力等のインタフェースで入力、出力、スクリプト入力、環境の四種類の変換を 使い分けます。

入力変換はファイルからデータを読み取るときに機能します。 INPUTテーブルを 作成するときと、 inputコマンドが影響を受けます。 入力変換のエンコーディングのみを変更するときには set iencコマンドを 使用します。

出力変換は標準出力へ出力するときに機能します。 SELECT文の出力が主ですが、SQLエラーが発生したときの エラーメッセージも変換の対象となります。 なお、SELECTの結果がBLOB型だった場合は変換の対象とは なりません。 出力変換のエンコーディングのみを変更するときには set oencコマンドを 使用します。

スクリプト入力変換はスクリプトファイルからの読み込みのときに機能します。 SQL文、squawkコマンドのいずれも変換の対象となります。 ただし-cオプションで指定した SQL文は常に環境変換で変換されます。 スクリプト入力変換のエンコーディングのみを変更するときには set sencコマンドを 使用します。 なお、スクリプト入力変換のエンコーディングにはASCIIの範囲でASCIIと互換が あり、かつ変換状態を持たないエンコーディングを指定する必要があります。 具体的には、UTF-8やEUC-JPなどは指定できますが、UTF-16やISO-2022-JPなどを 指定することはできません。

環境変換はsquawkの実行環境のエンコーディングに 合わせて変換を行う必要があるときに機能します。 具体的には、コマンド引数の文字列や hostコマンドの引数、 spoolコマンドの ファイル名などが変換対象となります。 環境変換で使用するエンコーディングは起動時に決定され、実行中に 変更することはできません。

エンコーディングは set encodingコマンド などで変更できますが、既定値は 環境変数 SQUAWK_ENCODINGの設定に従います。 SQUAWK_ENCODINGには iconv_open(3)で指定可能なエンコーディングを指定します。 SQUAWK_ENCODINGを 省略した場合、squawkは 環境変数LANG等から 適切なエンコーディングを推定します。

環境変数

squawkは以下の環境変数を使用します。

SQUAWK_LANG

squawkが動作する言語を 指定します。

SQUAWK_ENCODING

squawkが使用するデフォルトの エンコーディングを指定します。

LANG, LC_ALL, ...

SQUAWK_LANGSQUAWK_ENCODINGを 省略した場合、これらの環境変数から言語やエンコーディングを推定します。

TZ

日付/時刻関数の動作は TZ環境変数の設定の影響を受けます。

HOME

squawkを対話的に起動した場合、コマンド履歴を ホームディレクトリの.squawk_historyファイルに保存します。

使用例

例 1. ユーザ名の一覧作成

/etc/passwdファイルから全ての ログインユーザ名を取得し、ユーザIDでソートして出力します。

set FS ':'
input PASSWD /etc/passwd
SELECT $1 FROM PASSWD ORDER BY int($3);

あるいは

$ squawk -F: -c 'SELECT $1 FROM INPUT ORDER BY int($3)' /etc/passwd

例 2. 行番号付加

ファイルに行番号をつけて出力します。

SELECT sprintf('%6d', FNR), $0 FROM INPUT ORDER BY NR;

例 3. 行数カウント

指定された各ファイルの行数と、全てのファイルの行数の合計を出力します。

SELECT sprintf('%6d', (SELECT count(*) FROM INPUT WHERE FN = IND)), ARG
  FROM ARGV ORDER BY IND; 
SELECT sprintf('%6d', count(*)), 'total' FROM INPUT;

例 4. echoのエミュレーション

スクリプトに渡された引数を出力します。

#!/usr/bin/env squawk
set noinput
set ORS ''
SELECT ARG || if(IND == (SELECT max(IND) FROM ARGV), u('\n'), ' ')
  FROM ARGV ORDER BY IND;

例 5. printenvのエミュレーション

環境変数の一覧を出力します。

#!/usr/bin/env squawk
set noinput
SELECT NAME || '=' || VALUE FROM ENVIRON;

例 6. Solarisの"showrev -p"出力の整形

Solarisの"showrev -p"コマンド出力から適用されている最新のパッチ番号の一覧を パッチ番号順に出力します。

#!/usr/bin/env squawk
SELECT sprintf('%06d-%02d', MAJOR, MAXMINOR) PATCH FROM
  (SELECT MAJOR, max(MINOR) MAXMINOR FROM
    (SELECT substr($2, 1, 6) MAJOR, substr($2, 8, 2) MINOR FROM INPUT)
    GROUP BY MAJOR)
  ORDER BY PATCH;

ライセンス

squawkはフリーソフトウェアです。一切の動作保証はありません。

バイナリの配布条件はGPLに従います。

ソースはファイルごとに条件が異なりますので、それぞれのソースファイルを 参照してください。