web-dev-qa-db-ja.com

コマンドラインで文字列を16進数に変換する

コマンドラインを使用して、 "Hello"を16進数で48 65 6c 6c 6fにできるだけ効率的に変換しようとしています。

printfとgoogleを試してみましたが、どこにも行けません。

どんな助けも大歓迎です。

よろしくお願いいたします。

26
Eamorr
echo -n "Hello" | od -A n -t x1

説明:

  • echoプログラムは、次のコマンドに文字列を提供します。
  • -nフラグは、「Hello」の最後に新しい行を生成しないようにエコーに指示します。
  • odプログラムは「8進ダンプ」プログラムです。 (8進数ではなく16進数でダンプするように指示するフラグを提供します。)
  • -A nフラグは--address-radix=nの省略形で、nは「なし」の省略形です。この部分がないと、コマンドは左側に醜い数値アドレスプレフィックスを出力します。これは大きなダンプには役立ちますが、短い文字列には不要です。
  • -t x1フラグは--format=x1の略であり、xは「16進数」の略で、1は1バイトを意味します。
55
TMS

明らかに、@ TMSはRTFMを実行できません。 (彼の以前の答えに対する彼のコメントを参照してください)

これを行い、必要なスペースを削除する場合:

echo -n "Hello" | od -A n -t x1 | sed 's/ *//g'

パイプラインの最初の2つのコマンドは、@ Jamesが編集したように、@ TMSの回答でよく説明されています。最後のコマンドは@TMSコメントとは異なり、正しく、テストされています。説明は次のとおりです。

  • seds tream ed itorです。
  • ss ubstituteコマンドです。
  • /は、正規表現を開きます-任意の文字を使用できます。 /は従来型ですが、XMLやパス名などの処理には不便です。
  • /または選択した代替文字は、正規表現を閉じ、置換文字列を開きます。
  • / */では、*は前の文字のシーケンス(この場合はスペース)と一致します。
  • /または選択した代替文字は、置換文字列を閉じます。この場合、置換文字列//は空です。つまり、一致が削除されます。
  • gは、この置換を行うオプションですg各行で1回だけではなく、各行でlobally。
  • 引用符はコマンドパーサーの混乱を防ぎます。シーケンス全体が最初のオプションとしてsedに渡されます。つまり、sedスクリプトです。

@TMSブレインチャイルド(sed 's/^ *//')は、各行の先頭からスペースのみを削除します(^は行の先頭に一致します-sed- speakの「パターンスペース」)。

さらに改行を削除したい場合、最も簡単な方法は追加することです

| tr -d '\n'

コマンドパイプに。次のように機能します。

  • |は、以前に処理されたストリームをこのコマンドの標準入力に送ります。
  • trtr anslateコマンドです。
  • -dは、一致文字の削除を指定します。
  • 引用符には一致文字がリストされます-この場合は改行(\n)だけです。 Translateは、シーケンスではなく単一の文字にのみ一致します。

sedは、改行を処理するときに一意に遅延します。これは、sedが最も古いunixコマンドの1つであるためです。これは、人々が実際に何をしているかを知る前に作成されました。 Pervasiveのレガシーソフトウェアは、修正されないようにします。 unixが生まれる前に生まれたので、これを知っています。

問題の歴史的な起源は、改行が行の一部ではなく行の区切りであるという考えでした。したがって、ライン処理ユーティリティによって削除され、出力ユーティリティによって再挿入されました。問題は、これがユーザーデータの構造に関する仮定を行い、多くの設定で不自然な制限を課すことです。 sedが改行を簡単に削除できないことは、悲惨な原因となっている不正なイデオロギーの最も一般的な例の1つです。

sedを使用して改行を削除することは可能です-私が知っているすべての解決策は、ファイル全体を一度にsedで処理することです。編集者。可能であれば、ライン処理を保持するソリューションは、複数のパイプの読み取り不可能なネズミの巣になります。

sedの使用を主張する場合は、次のことを試してください。

sed -z 's/\n//g'

-zは、sedにnullを行区切り文字として使用するように指示します。

内部的には、Cの文字列はnullで終了します。 -zオプションもレガシーの結果であり、C- stringsで満たされた改行で整理された一時ファイルを使用したいCプログラマーの便宜のために提供されています。その後、一度に1つの文字列を簡単に読み取って処理できます。繰り返しになりますが、ユースケースに関する初期の想定では、ユーザーデータに人為的な制限を課しています。

gオプションを省略すると、このコマンドは最初の改行のみを削除します。 -zオプションを使用すると、sedはファイル全体を1行として解釈し(ファイルにヌルが埋め込まれていない限り)、ヌルで終了するため、大きなファイルでも窒息します。

あなたが考えるかもしれません

sed 's/^/\x00/' | sed -z 's/\n//' | sed 's/\x00//'

うまくいくかもしれません。最初のコマンドは、行ごとに各行の先頭にnullを配置し、\n\x00はすべての行を終了します。 2番目のコマンドは、ヌルで区切られた各行から1つの改行を削除します。最初のコマンドにより、改行は1つだけになります。残っているのは偽のヌルだけです。ここまでは順調ですね。ここで壊れたアイデアは、パイプが最後のコマンドを行ごとに供給するということです。これは、ストリームが構築された方法だからです。実際、最後のコマンドは、記述されているように、ファイル全体に改行がなく、したがって1行なので、1つのnullのみを削除します。

単純なパイプの実装は中間の一時ファイルを使用し、すべての入力が処理されてファイルに送られます。次のコマンドは別のスレッドで実行され、そのファイルを同時に読み取っていますが、ストリーム全体を(不完全ではありますが)見ているだけで、ファイルを供給するチャンクの境界を認識していません。パイプがメモリバッファーであっても、次のコマンドはストリーム全体を認識します。欠陥は不可分にsedに組み込まれます。

このアプローチを機能させるには、最後のコマンドにgオプションが必要です。この場合も、大きなファイルではチョークが発生します。

つまり、改行の処理にsedを使用しないでください。

これをさらに試してみると、「*」を削除することが解決策です。実際の文字を置き換える必要がある場合は、元の要件でスペースも削除する必要はありません。

echo -n "Hello" | od -A n -t x1 | sed 's/ /%/g'

%48%65%6c%6c%6f

だから、私はこれが元のQに答える改善であると考えています。なぜなら、このステートメントは、明らかにだけでなく、必要なものを正確に実行するからです。

1
Tony Su