80

在字符串“12345”中,在字符串“54321”中。最好没有第三方工具和正则表达式。

4

13 回答 13

185

我知道你说“没有第三方工具”,但有时一个工具显然是正确的,而且它默认安装在大多数 Linux 系统上:

[madhatta@risby tmp]$ echo 12345 | rev
54321

有关更多信息,请参见rev的手册页

于 2011-01-23T08:35:13.220 回答
32

简单的:

var="12345"
copy=${var}

len=${#copy}
for((i=$len-1;i>=0;i--)); do rev="$rev${copy:$i:1}"; done

echo "var: $var, rev: $rev"

输出:

$ bash rev
var: 12345, rev: 54321
于 2011-01-23T06:41:15.103 回答
15

假设变量“var”的值为“123”

var="123"

反转字符串并存储在新变量“rav”中:

rav=$(echo $var | rev)

您会看到使用 echo 的 'rav' 的值为 '321'。

echo $rav
于 2014-02-12T22:00:22.843 回答
12

rev | tail -r(BSD) 或rev | tac(GNU) 也反转行:

$ rev <<< $'12\n34' | tail -r
43
21
$ rev <<< $'12\n34' | gtac
43
21

如果 LC_CTYPE 是 C,rev 反转多字节字符的字节:

$ LC_CTYPE=C rev <<< あの
��め�
$ export LC_ALL=C; LC_ALL=en_US.UTF-8 rev <<< あの
のあ
于 2013-04-11T08:56:20.643 回答
9

一个 bash 解决方案改进了@osdyng 的答案(我的编辑未被接受):

var="12345"     rev=""

for(( i=0 ; i<${#var} ; i++ )); do rev="${var:i:1}$rev"; done

echo "var: $var, rev: $rev"

或者更简单的(bash)循环:

var=$1   len="${#var}"   i=0   rev=""

while (( i<len )); do rev="${var:i++:1}$rev"; done

echo "var: $var, rev: $rev"

POSIX 解决方案:

var="12345"     rev=""    i=1

while  [ "$i" -le "${#var}" ]
do     rev="$(echo "$var" | awk -v i="$i" '{print(substr($0,i,1))}')$rev"
       : $(( i+=1 ))
done

echo "var: $var, rev: $rev"

注意:这适用于多字节字符串。剪切解决方案仅适用于 ASCII(1 字节)字符串。

于 2016-01-08T01:50:36.713 回答
6

这将字符串“就地”反转:

a=12345
len=${#a}
for ((i=1;i<len;i++)); do a=$a${a: -i*2:1}; done; a=${a:len-1}
echo $a

或者第三行可能是:

for ((i=0;i<len;i++)); do a=${a:i*2:1}$a; done; a=${a:0:len}

或者

for ((i=1;i<len;i++)); do a=${a:0:len-i-1}${a: -i:i+1}${a:len-i-1:1}; done
于 2011-01-23T07:13:11.310 回答
6

反转字符串的一些简单方法

echo '!!!esreveR si sihT' | grep -o . | tac | tr -d '\n' ; echo

echo '!!!esreveR si sihT' | fold -w 1 | tac | tr -d '\n' ; echo

转换为十六进制值然后反转

echo '!!!esreveR si sihT' | xxd -p | grep -o .. | tac | xxd -r -p ; echo

echo '!!!esreveR si sihT' | xxd -p | fold -w 2 | tac | xxd -r -p ; echo
于 2017-10-05T20:26:29.910 回答
6

对于那些没有rev(推荐)的人,有以下简单的awk解决方案,它拆分空字符串上的字段(每个字符都是一个单独的字段)并反向打印:

awk -F '' '{ for(i=NF; i; i--) printf("%c", $i); print "" }'

上面的awk代码是 POSIX 兼容的。由于保证了兼容的awk实现在每个 POSIX 兼容的操作系统上,因此不应将解决方案视为“第 3 方”。此代码可能比纯 POSIX sh(或bash)解决方案更简洁易懂。

(;我不知道您是否将 -F 的空字符串视为正则表达式...;)

于 2016-01-08T05:18:20.557 回答
4

如果var=12345

for((i=0;i<${#var};i++)); do rev="$rev${var:~i:1}"; done

c=$var; while [ "$c" ]; do rev=$rev${c#"${c%?}"}; c=${c%?}; done

echo "var: $var, rev: $rev"

运行:

$ rev
var: 12345, rev: 54321
于 2016-12-11T02:09:34.537 回答
3

这当然可以缩短,但应该很容易理解:最后print添加了换行符。

echo 12345 | awk '{for (i = length($0); i > 0; i--) {printf("%s", substr($0, i, 1));} print "";}'
于 2015-04-10T15:20:39.860 回答
3

似乎没有人发布sed解决方案,所以这里有一个适用于非 GNU sed 的解决方案(所以我不会认为它是“第 3 方”)。它确实使用 regex 捕获单个字符.,但这是唯一的正则表达式。

分两个阶段:

$ echo 123456 | sed $'s/./&\\\n/g' | sed -ne $'x;H;${x;s/\\n//g;p;}'
654321

这使用 bash 格式替换在脚本中包含换行符(因为问题被标记为)。它首先将输入字符串分成每个字符一行,然后将每个字符插入到保持缓冲区的开头。

  • x交换保持空间和模式空间,并且
  • HH 将(当前)模式空间附加到保持空间。

因此,对于每个字符,我们将该字符放入保存空间,然后将旧的保存空间附加到它,从而反转输入。最后一个命令删除换行符以重建原始字符串。

这应该适用于任何单个字符串,但它将多行输入连接到单个输出字符串中。

于 2018-01-14T03:21:55.360 回答
1

这是另一个更简单的awk解决方案:

awk 'BEGIN{FS=""} {for (i=NF; i>0; i--) s=s $i; print s}' <<< '123456'

654321
于 2020-02-27T21:04:29.963 回答
-1

读单词

reve=`echo "$word" | awk '{for(i=length($0); i>0;i--) printf (substr($0,i,1));}'`
echo  "$reve"
于 2019-10-21T15:48:34.463 回答