J'ai un fichier texte de plus de 10 000 lignes. Dans ce fichier, j'ai un numéro de ligne 713 contenant trois nombres hexadécimaux comme, 7E 42 C0. J'ai besoin de le convertir en décimal. Mon code fonctionne bien si je ne donne que ce numéro dans un fichier texte. Mais, je veux donner le fichier et le numéro de ligne de ce fichier

Comme dans ce qui suit:

while read p q r; 
  do 

   printf "%d %d %d\n" 0x$p 0x$q 0x$r; 

 done   < $(sed -n '713p' run21.txt);

Mais cela n'a pas fonctionné et m'a donné une erreur de ambiguous redirect. S'il vous plaît, faites-moi savoir une solution.

-1
hassan 20 avril 2017 à 19:43

3 réponses

Meilleure réponse

Vous êtes sur la bonne voie, pour passer de hex à dec utilisation bc avec ibase et obase définis, par exemple

$ echo "obase=10; ibase=16; $(sed -n 713p run21.txt)" | bc

Quelle que soit la valeur hex à la ligne 713, elle sera affichée sous la forme decimal. Vous pouvez utiliser read -r a b c pour lire les 3 valeurs et les convertir chacune de manière similaire. Ou vous pouvez supprimer l'espace blanc entre les 3 valeurs hexadécimales et le convertir en une seule valeur décimale en fonction de vos besoins. Par exemple:

hexval=""
for i in $(sed -n 713p run21.txt); do
    hexval="$hexval$i"
done
echo "obase=10; ibase=16; $hexval" | bc

Sortie

8274624

Pour convertir chacun séparément, vous pouvez faire:

for i in $(sed -n 713p run21.txt); do
    printf " %d" "$(echo "obase=10; ibase=16; $i" | bc)"
done
printf "\n"

Sortie

126 66 192

Pour rendre la conversion plus robuste, vous pouvez (et devriez) ajouter une validation de toutes les valeurs lues en entrée. Vous pouvez faire beaucoup plus de validation quant au type de caractères lus dans chaque variable, mais vous devez au moins valider lire ET remplir le nombre de valeurs que vous attendiez. En mettant cela ensemble et en utilisant read pour lire et valider les 3 valeurs, vous pouvez faire quelque chose comme ce qui suit.

Le script prend le line_to_read comme premier argument obligatoire et le filename à lire comme son deuxième argument facultatif (il lira depuis stdin par défaut):

#!/bin/bash

test -z "$1" && {   ## validate line number given
    printf "error: insufficient input.\nusage: %s line [file (stdin)]\n" "${0##*/}"
    exit 1
}

test "$1" -eq "$1" &>/dev/null || {  ## test $1 is an integer value
    printf "error: first parameter not an integer '%s'\n" "$1"
    exit 1
}

fn="$2" ## read from filename as 2nd parameter (or by default from stdin)
test -f "$fn" || fn=/dev/stdin

read -r a b c < <(sed -n "${1}p" "$fn")     ## read each of the values

test -n "$a" -a -n "$b" -a -n "$c" || {     ## validate all 3 vars filled
    printf "error: less than 3 values on line '%s',\n" "$1"
    exit 1
}

printf "input : %3x %3x %3x\n" "0x$a" "0x$b" "0x$c" ## output original line
## output line converted from hex to decimal
printf "output: %3d %3d %3d\n" $(echo "obase=10; ibase=16; $a" | bc) \
$(echo "obase=10; ibase=16; $b" | bc) $(echo "obase=10; ibase=16; $c" | bc)

Exemple d'entrée

$ cat dat/3hex.txt
7E 42 C0

Exemple d'utilisation / de sortie

$ bash 3hexcvt.sh 1 <dat/3hex.txt
input :  7e  42  c0
output: 126  66 192
1
David C. Rankin 20 avril 2017 à 19:30

@David j'ai fait ça

while read -r p q r; 
  do 

   #printf "%d %d %d\n" 0x$p 0x$q 0x$r; 
   #printf "%d %d %d\n"
   echo "obase=10; ibase=16; $(sed -n 713p run21.txt)" | bc ;

  done

Mais il n'y a pas de sortie.

0
hassan 20 avril 2017 à 17:14

Peut-être plus simple de cette façon ...

read p q r < <(sed -n '713{p;q}' file);  printf "%d %d %d\n" 0x$p 0x$q 0x$r;
0
karakfa 20 avril 2017 à 17:11