Bash命令用于提取字符串中的字符

时间:2013-12-19 14:12:59

标签: bash nginx sed awk

我想编写一个小脚本来生成NGINX缓存目录中文件的位置。 路径的格式为:

/path/to/nginx/cache/d8/40/32/13febd65d65112badd0aa90a15d84032

注意最后6个字符:d8 40 32,在路径中表示。

作为输入,我给出了md5哈希(13febd65d65112badd0aa90a15d84032),我想生成输出:d8/40/32/13febd65d65112badd0aa90a15d84032

我确定sed或awk会派上用场,但我还不知道怎么样......

5 个答案:

答案 0 :(得分:1)

这个awk可以做到:

awk 'BEGIN{FS=""; OFS="/"}{print $(NF-5)$(NF-4), $(NF-3)$(NF-2), $(NF-1)$NF, $0}'

解释

  • BEGIN{FS=""; OFS="/"}FS=""将输入字段分隔符设置为"",以便每个字符都是不同的字段。对于OFS="/"事项,/将输出字段分隔符设置为print
  • print ... $(NF-1)$NF, $0将倒数第二个字段和最后一个字段打印在一起;然后,整个字符串。逗号被OFS“填充”,即/

测试

$ awk 'BEGIN{FS=""; OFS="/"}{print $(NF-5)$(NF-4), $(NF-3)$(NF-2), $(NF-1)$NF, $0}' <<< "13febd65d65112badd0aa90a15d84032"
d8/40/32/13febd65d65112badd0aa90a15d84032

或者使用文件:

$ cat a
13febd65d65112badd0aa90a15d84032
13febd65d65112badd0aa90a15f1f2f3

$ awk 'BEGIN{FS=""; OFS="/"}{print $(NF-5)$(NF-4), $(NF-3)$(NF-2), $(NF-1)$NF, $0}' a
d8/40/32/13febd65d65112badd0aa90a15d84032
f1/f2/f3/13febd65d65112badd0aa90a15f1f2f3

答案 1 :(得分:1)

使用sed

echo '13febd65d65112badd0aa90a15d84032' | \
  sed -n 's/\(.*\([0-9a-f]\{2\}\)\([0-9a-f]\{2\}\)\([0-9a-f]\{2\}\)\)$/\2\/\3\/\4\/\1/p;' 

拥有GNU sed,您甚至可以使用-r选项简化模式。现在您不再需要转义{}()了。使用~作为正则表达式分隔符允许使用路径分隔符/而无需转义它:

sed -nr 's~(.*([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2}))$~\2/\3/\4/\1~p;' 

输出:

d8/40/32/13febd65d65112badd0aa90a15d84032

简单解释该模式执行以下操作:匹配:

(all (n-5 - n-4) (n-3 - n-2) (n-1 - n-0))

并将其替换为

/$1/$2/$3/$0

答案 2 :(得分:0)

您可以使用正则表达式将最后3个字节中的每一个与散列的其余部分分开。

hash=13febd65d65112badd0aa90a15d84032
[[ $hash =~ (..)(..)(..)$ ]]
new_path="/path/to/nginx/cache/${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/${BASH_REMATCH[3]}/$hash"

答案 3 :(得分:0)

Base="/path/to/nginx/cache/"
echo '13febd65d65112badd0aa90a15d84032' | \
 sed "s|\(.*\(..\)\(..\)\(..\)\)|${Base}\2/\3/\4/\1|"

# or
# sed sed 's|.*\(..\)\(..\)\(..\)$|${Base}\1/\2/\3/&|'

假设信息是正确的MD5(且仅限)字符串

答案 4 :(得分:0)

首先 - 感谢所有响应者 - 这非常快! 我也同时做了自己的脚本编写,并提出了这个解决方案:

使用您要查找的网址参数运行此脚本(例如www.example.com/article/76232?q=hello

#!/bin/bash 
path=$1
md5=$(echo -n "$path" | md5sum | cut -f1 -d' ')
p3=$(echo "${md5:0-2:2}")
p2=$(echo "${md5:0-4:2}")
p1=$(echo "${md5:0-6:2}")
echo "/path/to/nginx/cache/$p1/$p2/$p3/$md5"

这假设NGINX缓存的密钥结构为2:2:2