文字列(ハッシュ値)の長さを単純に計算したかったのです。だから、私はターミナルを開いてこれをしました:
_$ apropos length
_
その結果、_(3)
_または_(3ssl)
_が末尾に追加された一連のコマンド/関数が返されました。ここでman manは、これらの_section numbers
_の意味についての情報を提供します。
_3 Library calls (functions within program libraries)
_
好奇心から、私はこれらすべてのコマンドを試してみました(少なくとも1つがうまくいくことを願っています)
_strcspn (3) - get length of a prefix substring
strlen (3) - calculate the length of a string
strnlen (3) - determine the length of a fixed-size string
strspn (3) - get length of a prefix substring
wcslen (3) - determine the length of a wide-character string
wcsnlen (3) - determine the length of a fixed-size wide-character string
_
すべてのコマンドで同じエラーしか出てこなかった
_$ strnlen HelloWorld
$ strnlen: command not found
_
まあ、私は知っていますシェルで文字列の長さを見つける方法_wc -m
_、_expr length
_およびその他の回避策。
しかし、ここで2つの質問があります。
library calls (3)
を使用する方法?注:質問では、一般的に_library calls
_と、シェルでの使用に焦点を当てています。そのため、最初の質問に答えることがより重要になります。
あなたはおそらくこれを行うべきではありませんが、できます。 Kusalanandaの回答 は、目前のタスクに適し、問題を説明します。端末内でanyライブラリ呼び出しを使用する方法を具体的に尋ねたので、ここにいくつかの方法があります...
Tiny Cコンパイラ(tcc
)は_-run
_フラグ をサポートしています。これにより、小さなプログラムを作成することで(事実上)Cコードを解釈できるため、can単一の呼び出しでターミナル内のライブラリ呼び出しを使用します。
次のようにstrnlen
関数を実行できます。
_$ tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", strnlen(argv[1], 1024));}') "Hello world"
11
_
これは、Bash、zsh、およびその他のシェルからの プロセス置換 を使用して、tcc
にすべてのecho
sの結果を含むように見える読み取りファイルを提供します。他のオプションがあります。
これを生成する関数を作成できます。
_call_library_function_s_i() {
func=$1
shift
tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", '$func'(argv[1]));}') "$*"
}
$ call_library_function_s_i strlen hello world
_
(ここではstrlen
を使用して、単項関数string-> intにしています-異なるアリティと戻り値の型ごとに個別の関数が必要です)。
別のオプションは、Tavis Ormandyによる the _ctypes.sh
_ Bash plugin で、dlopen
とdlsym
をラップします。これはおそらく、あなたが試みていたものに最も近い近似です。たとえば、次のように使用できます。
_$ dlcall -r uint64 strlen "hello world"
_
期待どおりに関数を呼び出します。
これは「ターミナルから」それを行う最も直接的な方法ですが、配布パッケージに含まれている可能性は低いため、手動でインストールする必要があります(これは重要です)。ここにいくつかの有益な _ctypes.sh
_の自身のウェブサイトからの引用 がこれを行うことについて人々がどのように感じているかについての一般的な印象を与えるために:
- 「嫌だ」
- 「これは止めなければならない」
- 「あなたはこれで行き過ぎました」
他のシェルにも同様のツールがあるかもしれませんが、私はそれらについて知りません。理論的には、単純なケースでこれを正確に実行するスタンドアロンコマンドが存在し得ない理由はありませんが、それを見つけることができなかったことに少し驚いています...
...だから作成しました!dlcall
を使用すると、コマンドラインからライブラリ関数を呼び出すことができます :
_$ dlcall strnlen "hello world" 6
$ dlcall sin 2.5
$ dlcall strchr "hello world" -c ' '
_
それは機能プロトタイプの限られたセットをサポートします、それは現在ひどく信頼性や弾力性はありませんが、それは現在存在しています。
たとえば Pythonおよびpython -c 'import ctypes; import sys; print(ctypes.cdll.LoadLibrary("libc.so.6").strlen(" ".join(sys.argv[1:])))' hello world
を使用することもできますが、それは確かに最も簡単な方法ではありません。 Perl、Ruby、およびその他の言語には、使用できる同様の機能があります。
だからあなたの質問への答えは:
全体として、他の方法でこれを行う方が確実に良いでしょう。
apropos
コマンドは多くの点で役立ちますが、多くの「ジャンク」も提供します。リストするもののほとんどはCライブラリルーチン(これは、マニュアルのセクション3が対象です)であり、シェルから直接使用することはできません。
それらを使用するには、それらを呼び出すCプログラムを作成する必要があります。これは、この特定のサイトでカバーされているトピックの範囲外です( StackOverflow のトピックにあります)。
したがって、これらはあなたの質問に対する答えです:
私はあなたがこれを知っていることを知っていますが、完全を期すために:シェルで、変数string
に文字列がある場合、次のようにすることができます
string='hello world'
printf 'Length of string "%s" is %d\n' "$string" "${#string}"
これにより、Length of string "hello world" is 11
が11
から取得されるターミナルに${#string}
が出力され、$string
の文字列の長さに展開されます。
内部的には、シェルは長さの計算を行うためにリストしたライブラリー呼び出しの1つを使用している可能性があります。
これは、シェルで、シェル変数に格納されている文字列の長さを取得する最も効率的な方法です。
${#string}
は POSIXシェルパラメータ展開 であることにも注意してください。したがって、ある程度のPOSIX準拠を主張するすべてのシェル間で移植可能です。
strlen()
だけでこれを行うことはしませんが、Cコードを試すのに役立つトリックです。
user @ Host:〜$ gdb gdb (gdb)start 一時ブレークポイント1、... in main() (gdb)print strlen( " foobar ") $ 1 = 6
ここでgdb
はGNUデバッガーであり、通常はその後にデバッグするためにプログラム名を必要とします。何もないため、この例ではデバッグするためにそれ自体を与えています。次にstart
はプログラムを起動し、その後gdb
を使用して任意のCコードを実行できます。
共有ライブラリの関数をインタラクティブに呼び出すために使用できるツール:「Witchcraftコンパイラコレクション」。 https://github.com/endrazine/wcc
GitHubページから:
wsh:Witchcraft Shell
Witchcraftシェルは、ELF共有ライブラリ、ELF ET_DYN実行可能ファイル、およびPunk-Cで記述されたWitchcraftシェルスクリプトを入力として受け入れます。すべての実行可能ファイルを独自のアドレス空間にロードし、そのAPIを組み込みインタープリターでプログラミングできるようにします。これにより、Javaなどの言語でのリフレクションを介して提供されるものと同様のバイナリ機能が提供されます。
wshの使用例次のコマンドは、wsh内の_
/usr/sbin/Apache2
_実行可能ファイルをロードし、Apache内のap_get_server_banner()
関数を呼び出して取得しますバナーを表示し、wsh
インタープリター内に表示します。
_jonathan@blackbox:~$ wsh /usr/sbin/Apache2
> a = ap_get_server_banner()
> print(a)
Apache/2.4.7
_