需要一个Shell脚本将大端序转换为小端序。

10

我需要一个shell脚本程序,将大端序的十六进制数转换为小端序。

例如

  • 输入:my virtual address = 00d66d7e
  • 输出:7e6dd600

我如何在bash脚本中创建它?


看起来像是简单的字符串操作。 - Karoly Horvath
1
为什么不展示你所尝试的内容呢? Stackoverflow 不是用来提出请求的,它是用来回答问题的。 - phuclv
1
另外,C语言与shell有什么关系?以及是哪个shell? - phuclv
6个回答

17

刚刚必须要这么做...但是从十进制到小端序...现在在这里适应:

echo 00d66d7e | tac -rs .. | echo "$(tr -d '\n')"

实现对于任意大小的无符号整数十六进制表示的所需结果。

(感谢MestreLion的建议 'tac -rs',非常好!)


3
非常聪明的解决方案,加一分!我能否提出改进意见?tac,至少GNU tac,接受正则表达式作为分隔符,因此不需要使用grep: echo "AABBCC" | tac -rs .. - MestreLion
注意,不寻常的echo "$()"机制基本上只是为了在末尾获取一个换行符...可以用{ tr -d '\n'; echo; }或类似的东西替换它。 - Brian Chrisman
2
非常好的解决方案。我更喜欢echo -n 00d66d7e | tac -rs .. ; echo,但这只是个人口味而已。 - Benoit Duffez

15

对于32位地址,假设它是用零填充的:

v=00d66d7e 
echo ${v:6:2}${v:4:2}${v:2:2}${v:0:2}
# 7e6dd600

12

根据Karoly的回答,您可以使用以下脚本来读取参数或管道输入并进行大小端转换:

#!/bin/bash

# check 1st arg or stdin
if [ $# -ne 1 ]; then
  if [ -t 0 ]; then
    exit
  else
    v=`cat /dev/stdin`
  fi
else
  v=$1
fi

i=${#v}

while [ $i -gt 0 ]
do
    i=$[$i-2]
    echo -n ${v:$i:2}
done

echo

比如,您可以将此脚本保存为endian.sh,并使用以下命令使其可执行:

chmod u+x endian.sh

那么:

echo 00d66d7e | ./endian.sh

为您提供:

7e6dd600

对于不同长度的字符串:

echo d76f411475428afc90947ee320 | ./endian.sh

结果将是:

20e37e9490fc8a427514416fd7

#更新: 修改了脚本,使其可以通过参数或从stdin输入,以满足Freewind的要求。现在:

./endian.sh d76f411475428afc90947ee320

也可以工作,并提供给您:

20e37e9490fc8a427514416fd7

如何更改脚本以使其与 ./endian.sh d76f411475428afc90947ee320 一起工作?谢谢! - Freewind
@Freewind 我的回答(https://dev59.com/DmEh5IYBdhLWcg3whT_T#55731305) 解决了你的问题。 - rolling_codes
修改了脚本,使其能够使用参数运行。@Freewind - hutheano

3
这适用于dash(以及许多其他shell):
v=0x12345678
v2=$(( (v<<8 & 0xff00ff00) | (v>>8 & 0xff00ff) ))
v2=$(( (v2<<16 & 0xffff0000) | v2>>16 ))
printf '0x%08x\n' $v2

结果应该是“0x78563412”。
${v:6:2} is for bash.

1
作为对Freewind评论请求的回应,并在hutheano的优秀答案的基础上构建,我编写了自己的bash脚本,并在下面包含了精简版本。完整脚本可在此处下载。 以下实现考虑到奇数长度字符串、0x\x前缀和多种输出格式,并可使用如下:
$ be2le d76f411475428afc90947ee320 0xaaff 0xffa '\x3'
20e37e9490fc8a427514416fd7
0xffaa
0xfa0f
\x03

be2le bash脚本

#!/bin/bash

args=()

format=preserve
delimiter="\n"
nonewline=false
join=false
strip=false

while (( "$#" )); do
    case "$1" in
        -h|--help) usage;;
        -f) format=$2; shift 2;;
        --format=*) format="${1#*=}"; shift;;
        -d) delimiter=$2; shift 2;;
        --delimiter=*) delimiter="${1#*=}"; shift;;
        -n|--no-newline) nonewline=true; shift;;
        -j|--join) join=true; shift;;
        -s|--strip-null) strip=true; shift;;
        -*|--*) echo "Error: unsupported flag $1 specified"; exit 1;;
        *) args=( "${args[@]}" "$1" ); shift;;
    esac
done

case "$format" in
    preserve);;
    int) prefix="0x";;
    char) prefix="\x";; 
    raw) ;;
    *) echo "Error: unsupported format $format"; exit 1;;
esac

n=0
parts=()
for arg in ${args[@]}; do

    digest=""
    prefix=""

    # remove prefix if string begins with "0x"
    if [[ $arg =~ ^[0\\]x ]]; then
        if [ "$format" == "preserve" ]; then
            prefix=${arg:0:2}
        fi
        arg=${arg:2}
    fi

    # zero-pad if string has odd length
    if [ $[${#arg} % 2] != 0 ]; then
        arg="0$arg"
    fi

    part=""
    i=${#arg}
    while [ $i -gt 0 ]; do
        i=$[$i-2]
        byte=${arg:$i:2}
        if [ $strip == true ] && [ -z "$part" ] && [ $byte == "00" ]; then
            continue
        fi
        case "$format" in
            int) part="$part"'0x'"$byte ";;
            char) part="$part\x$byte";;
            raw) part="$part$(printf "%b" "\x$byte")";;
            *) part="$part$byte";;
        esac
    done

    digest="$prefix$digest$part"

    parts=( "${parts[@]}" "$digest" )
    n=$[$n+1]

done

if [ $join == true ]; then
    case "$format" in
        *) printf "%s" "${parts[@]}";;
    esac
else
    i=0
    for part in "${parts[@]}"; do
        if [[ $(($i + 1)) < $n ]]; then
            printf "%s$delimiter" "$part"
        else
            printf "%s" "$part"
        fi
        i=$(($i+1))
    done
fi

if [ $nonewline == false ]; then
    echo
fi

0

这个脚本是用于翻转16位数据的。

#!/bin/bash

if [ -t 0 ]; then exit; fi

data=`cat /dev/stdin | od -An -vtx1 | tr -d ' ' | tr -d '\n'`
length=${#data}

i=0
while [ $i -lt $length ]; do
    echo -n -e "\x${data:$[$i+2]:2}"
    echo -n -e "\x${data:$[$i]:2}"
    i=$[$i+4]
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接