Je voulais simplement calculer la longueur d'une chaîne (c'est-à-dire la valeur de hachage). J'ai donc ouvert le terminal et j'ai fait ceci:
$ apropos length
qui m'a renvoyé un tas de commandes/fonctions ayant (3)
ou (3ssl)
ajouté à la fin d'entre eux. Maintenant man man nous donne des informations sur ce que ces section numbers
Signifient.
3 Library calls (functions within program libraries)
Par curiosité, j'ai juste essayé avec toutes ces commandes (en espérant qu'au moins une fonctionnerait)
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
et n'a obtenu que la même erreur pour chaque commande
$ strnlen HelloWorld
$ strnlen: command not found
Eh bien, je sais comment trouver la longueur d'une chaîne dans Shell en utilisant wc -m
, expr length
et d'autres solutions.
Mais, j'ai 2 questions ici:
library calls (3)
à l'intérieur du shell?REMARQUE: la question se concentre en général sur library calls
Et leur utilisation dans le shell. Cela rend la première question plus importante à répondre.
Vous probablement ne devriez pas faire cela, mais vous pouvez. réponse de Kusalananda est mieux pour la tâche à accomplir et explique le problème. Puisque vous avez demandé spécifiquement comment utiliser les appels à la bibliothèque any à l'intérieur du terminal, voici quelques façons ...
Le Tiny C Compiler (tcc
) prend en charge un indicateur -run
qui vous permet (en effet) d'interpréter le code C en écrivant un petit programme, donc vous peut utiliser tous les appels de bibliothèque à l'intérieur du terminal via une seule invocation de cela.
Vous pouvez exécuter la fonction strnlen
comme ceci:
$ 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
Cela utilise substitution de processus de Bash, zsh et d'autres shells pour donner à tcc
un fichier à lire qui semble contenir les résultats de tous les echo
s; il existe d'autres options.
Vous pouvez créer une fonction pour générer ceci pour vous:
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
(J'ai utilisé strlen
ici pour que ce soit une chaîne de fonction unaire -> int - vous auriez besoin d'une fonction distincte pour chaque arité et type de retour différents).
Une autre option est le plugin ctypes.sh
Bash par Tavis Ormandy, qui regroupe dlopen
et dlsym
. C'est probablement l'approximation la plus proche de ce que vous essayiez. Vous pouvez utiliser, par exemple:
$ dlcall -r uint64 strlen "hello world"
et il appellera la fonction comme prévu.
C'est le moyen le plus direct de le faire "à partir du terminal", mais il est peu probable que vos packages de distribution soient installés, vous devrez donc l'installer manuellement (ce qui n'est pas trivial). Voici quelques informations citations du propre site Web de ctypes.sh
pour donner une impression générale de la façon dont les gens se sentent à ce sujet:
- "c'est dégoutant"
- "cela doit s'arrêter"
- "tu es allé trop loin avec ça"
Il peut y avoir des outils similaires pour d'autres obus, mais je ne les connais pas. En théorie, il n'y a aucune raison qu'il ne puisse pas y avoir de commande autonome qui fasse exactement cela pour les cas simples, mais je suis quelque peu surpris de ne pas en avoir trouvé un ...
... alors j'en ai créé un! dlcall
vous permet d'appeler les fonctions de la bibliothèque à partir de la ligne de commande :
$ dlcall strnlen "hello world" 6
$ dlcall sin 2.5
$ dlcall strchr "hello world" -c ' '
Il prend en charge un ensemble limité de prototypes de fonctions, il n'est pas terriblement fiable ou résilient actuellement, mais il existe maintenant.
Vous pouvez également utiliser, par exemple, Python et python -c 'import ctypes; import sys; print(ctypes.cdll.LoadLibrary("libc.so.6").strlen(" ".join(sys.argv[1:])))' hello world
, mais ce n'est certainement pas la manière la plus simple de s'y prendre. Perl, Ruby et d'autres langages ont des fonctionnalités similaires que vous pourriez utiliser.
Les réponses à vos questions sont donc:
Dans l'ensemble, vous ferez certainement mieux de faire cela d'une autre manière.
La commande apropos
est utile à bien des égards, mais elle vous donne aussi beaucoup de "déchets". La plupart des choses que vous répertoriez sont des routines de bibliothèque C (c'est à cela que sert la section 3 du manuel), que vous ne pouvez pas utiliser directement à partir du shell.
Pour les utiliser, vous devez écrire un programme C qui les appelle. Cela tombe en dehors de la gamme de sujets couverts par ce site particulier (ce serait sur le sujet à StackOverflow ).
Voici donc les réponses à vos questions:
Je sais que vous le savez, mais pour être complet: dans le shell, si vous avez une chaîne dans une variable string
, vous pouvez faire
string='hello world'
printf 'Length of string "%s" is %d\n' "$string" "${#string}"
Cela imprimera Length of string "hello world" is 11
dans le terminal où le 11
vient de ${#string}
qui s'étend jusqu'à la longueur de la chaîne dans $string
.
En interne, le shell peut très bien utiliser l'un des appels de bibliothèque que vous avez répertoriés pour effectuer son calcul de longueur.
C'est le moyen le plus efficace pour obtenir la longueur d'une chaîne stockée dans une variable Shell, dans le Shell.
Notez également que ${#string}
est ne extension des paramètres du shell POSIX , il est donc portable entre tous les shells qui revendiquent n'importe quel degré de conformité POSIX.
Je ne ferais pas cela uniquement pour strlen()
, mais c'est une astuce utile pour essayer le code C parfois.
user @ Host: ~ $ gdb gdb (gdb) start Point d'arrêt temporaire 1, ... dans main () (gdb) print strlen (" foobar ") 1 $ = 6
Ici gdb
est le débogueur GNU, et il faudrait normalement un nom de programme pour le déboguer après. Parce que nous n'en avons pas, cet exemple le donne lui-même pour déboguer. Puis start
démarre le programme, et après cela gdb
peut être utilisé pour exécuter du code C arbitraire.
Un outil qui peut être utilisé pour appeler de manière interactive des fonctions dans des bibliothèques partagées: la "Witchcraft Compiler Collection". https://github.com/endrazine/wcc
Depuis la page GitHub:
wsh: La coquille de sorcellerie
Le shell de sorcellerie accepte les bibliothèques partagées ELF, les exécutables ELF ET_DYN et les scripts de shell Witchcraft écrits en Punk-C comme entrée. Il charge tous les exécutables dans son propre espace d'adressage et rend leur API disponible pour la programmation dans son interpréteur intégré. Cela fournit des fonctionnalités binaires similaires à celles fournies via la réflexion sur des langages comme Java.
Exemple d'utilisation de wsh La commande suivante charge l'exécutable
/usr/sbin/Apache2
Dans wsh, appelle la fonctionap_get_server_banner()
dans Apache pour récupérer sa bannière et l'afficher dans l'interpréteurwsh
.
jonathan@blackbox:~$ wsh /usr/sbin/Apache2
> a = ap_get_server_banner()
> print(a)
Apache/2.4.7