bcp
私はWindowsコンピュータでテキストファイルを扱っています。ユーティリティを使用してファイルのデータをデータベーステーブルにロードする前に、末尾のタブ文字を削除する必要があります。
Bashスクリプトの次のコマンドは、末尾のタブを削除します。
sed 's/[\t]*$//' < ./input/raw.txt >> ./input/data.txt
ただし、CR
-LF
コマンドが失敗した理由に変換されますLF
。bcp
維持しようとする努力の一環として、以下をCR
試しLF
ました。
sed 's/[\t]*$/$CR/' < ./input/raw.txt >> ./input/data.txt
しかし、結果は次のようになります。
必要な結果は次のとおりです。
目的の出力を取得するには、コマンドをどのように変更する必要がありますか?
答え1
このパッケージをインストールする必要がありますunix2dos
。これには2つのユーティリティがあります。
unix2dos Convert UNIX newlines to CR-LF
dos2unix Convert DOS CR-LF to UNIX newlines
5行のテストファイルを作成し、16進ダンプを実行して行の終わりを確認します。
$ jot -w 'line %d' 5 > foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0a 6c 69 6e 65 20 32 0a 6c 69 |line 1.line 2.li|
00000010 6e 65 20 33 0a 6c 69 6e 65 20 34 0a 6c 69 6e 65 |ne 3.line 4.line|
00000020 20 35 0a | 5.|
00000023
各行は改行文字(hex 0a)で終わることがわかります。
さて、これらの改行をDOS CR-LF行末に変換して再確認します。
$ unix2dos foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0d 0a 6c 69 6e 65 20 32 0d 0a |line 1..line 2..|
00000010 6c 69 6e 65 20 33 0d 0a 6c 69 6e 65 20 34 0d 0a |line 3..line 4..|
00000020 6c 69 6e 65 20 35 0d 0a |line 5..|
00000028
各行はCR-LF、hex 0d 0aで終わります。
最後に、ファイルを元のUNIX改行文字に戻すことができます。
$ dos2unix foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0a 6c 69 6e 65 20 32 0a 6c 69 |line 1.line 2.li|
00000010 6e 65 20 33 0a 6c 69 6e 65 20 34 0a 6c 69 6e 65 |ne 3.line 4.line|
00000020 20 35 0a | 5.|
00000023
答え2
標準では、sed
行末のsed 's/[\t]*$//'
すべてのバックスラッシュと文字が削除されます。 GNU実装は、t
その環境にsed
変数が存在する場合にのみこれを行います。POSIXLY_CORRECT
sed 's/\t*$//'
指定されていませんが、少なくとも GNU の場合、sed
環境の有無にかかわらず、末尾の TAB が削除されます。POSIXLY_CORRECT
ここでは、次のことができます。
sed $'s/\t*$/\r/'
それぞれTABとCRと同じまたは拡張されたksh93スタイルの$'...'
引用を使用してください。これは他の多くのシェルでサポートされており、POSIX規格の次のバージョンに表示されます。\t
\r
sh
シェル変数にTABおよびCR文字がある場合は、次の文字を使用する必要はありません。$'...'
例:
eval "$(printf 'TAB="\t" CR="\r"')"
次のことができます。
sed "s/$TAB*\$/$CR/"
ただし、二重引用符で囲む必要があります。一重引用符内では拡張は行われません。
入力がLF文字で終わらない場合(Unixでは無効なテキストになります)、その文字(sed
少なくともGNUの場合)はCR文字で終わるファイルを生成し、Unixでは無効になります。 DOSでも同様です。
UnixからDOSにテキストファイルを変換するには、このユーティリティを使用できますunix2dos
。問題はありません。
sed $'s/\t*$//' | unix2dos
または、次のパターンを使用しperl
てくださいsed
。
perl -pe 's/\t*$//; s/\n/\r\n/'
perl -p
行区切り文字を含む行全体を含むパターンスペース(そこ)をsed
除いて、各入力行に対してコードを実行するように機能します。また、、エスケープ文字をサポートし(標準は正規表現でのみおよびのみサポート)、テキストではなくファイルを処理できます。perl
$_
\t
\n
\r
sed
\n
答え3
使用幸せ(以前のPerl_6)
~$ cat unix2dos.raku
my $fh1 = open $*IN, :r;
#below :x opens write-only :exclusive (i.e. 'no-clobber')
my $fh2 = open $*OUT, :x, nl-out => "\r\n";
for $fh1.lines() { $fh2.put($_) };
$fh1.close;
$fh2.close;
Raku(Perl6とも呼ばれる)はPerlファミリーのプログラミング言語です。 Perl6プロジェクトが試みていることの1つは、コードの移植性を高めるためにオペレーティングシステム固有の問題を抽象化することであり、これらの問題の1つは改行です。 Rakuはnl-in
ファイルハンドル入力の引数(デフォルトは["\x0A", "\r\n"]
)を提供します。\n
デフォルトでは、 - を使用して改行を終了するために自動的に行を切り捨て、ファイルnl-out
ハンドル出力の引数を指定します(デフォルトは"\n"
)。
OPの主な声明は次のとおりです。
...しかし、これはbcpコマンドを失敗させる
CR-LF
と解釈されます。LF
したがって、上記のRakuスクリプトの場合(使用しているプラットフォームに関係なく)、書き込み用にファイルを開き、改行がnl-out => \r\n
CRLFであることを設定できます。 Rakuはゆっくり読み込むlines
ので、このスクリプトはメモリを節約する必要があります。上記のスクリプトを実行可能にすることなく、次のようにコマンドラインから呼び出すことができます。
~$ raku unix2dos.raku < ends_with_LF.txt > ends_with_CRLF.txt
上記のスクリプトはデフォルトでは$*IN
stdinなので、「使い捨て」ですが、Rakuは読み取り機能$*ARGFILES
とディレクトリ機能も提供します。dir
最後に、下の最初のリンクはRakuの改行処理の素晴らしい要約を提供します。