我想要反转一堆文件中的所有颜色值。颜色都是十六进制格式#ff3300
,因此可以使用sed命令以字符方式完成反转
y/0123456789abcdef/fedcba9876543210/
如何循环遍历所有颜色匹配并在sed或awk中进行字符翻译?
编辑:
示例输入:
random text... #ffffff_random_text_#000000__
asdf#00ff00
asdfghj
期望的输出:
random text... #000000_random_text_#ffffff__
asdf#ff00ff
asdfghj
答案 0 :(得分:2)
编辑:我根据你的编辑改变了我的回复。
好的,sed
可能会导致处理困难。 awk
可以或多或少地轻松完成这一操作,但我发现perl
更容易完成此任务:
$ perl -pe 's/#[0-9a-f]+/$&=~tr%0123456789abcdef%fedcba9876543210%r/ge' <infile >outfile
基本上你找到了模式,然后执行右侧,它在匹配上执行tr,并在那里替换值。
答案 1 :(得分:2)
反演实际上是减法。要反转十六进制,只需从ffffff
中减去它
考虑到这一点,您可以构建一个简单的脚本来处理每一行,提取六角形,反转它们,然后将它们注入回行。
这只是使用 Bash (请参阅数组,printf -v
,+=
等)(没有外部工具):
#!/usr/bin/env bash
[[ -f $1 ]] || { printf "error: cannot find file: %s\n" "$1" >&2; exit 1; }
while read -r; do
# split line with '#' as separator
IFS='#' toks=( $REPLY )
for tok in "${toks[@]}"; do
# extract hex
read -n6 hex <<< "$tok"
# is it really a hex ?
if [[ $hex =~ [0-9a-fA-F]{6} ]]; then
# compute inversion
inv="$((16#ffffff - 16#$hex))"
# zero pad the result
printf -v inv "%06x" "$inv"
# replace hex with inv
tok="${tok/$hex/$inv}"
fi
# build the modified line
line+="#$tok"
done
# print the modified line and clean it for reuse
printf "%s\n" "${line#\#}"
unset line
done < "$1"
使用它像:
$ ./invhex infile > outfile
测试用例输入:
random text... #ffffff_random_text_#000000__
asdf#00ff00
bdf#cvb_foo
asdfghj
#bdfg
已处理的输出:
random text... #000000_random_text_#ffffff__
asdf#ff00ff
bdf#cvb_foo
asdfghj
#bdfg
答案 2 :(得分:2)
这可能适合你(GNU sed):
sed '/#[a-f0-9]\{6\}\>/!b
s//\n&/g
h
s/[^\n]*\(\n.\{7\}\)[^\n]*/\1/g
y/0123456789abcdef/fedcba9876543210/
H
g
:a;s/\n.\{7\}\(.*\n\)\n\(.\{7\}\)/\2\1/;ta
s/\n//' file
说明:
/#[a-f0-9]\{6\}\>/!b
在不包含所需模式的行上挽救s//\n&/g
在每个模式前加上换行符h
将此内容复制到暂停空间s/[^\n]*\(\n.\{7\}\)[^\n]*/\1/g
删除除了所需模式之外的所有内容y/0123456789abcdef/fedcba9876543210/
转换模式H
将新模式附加到保留空间g
用保留空间的内容覆盖模式空间:a;s/\n.\{7\}\(.*\n\)\n\(.\{7\}\)/\2\1/;ta
用新的替换旧模式。s/\n//
从H
命令中删除换行工件。答案 3 :(得分:1)
这有效......
cat test.txt |sed -e 's/\#\([0123456789abcdef]\{6\}\)/\n\#\1\n/g' |sed -e ' /^#.*/ y/0123456789abcdef/fedcba9876543210/' | awk '{lastType=type;type= substr($0,1,1)=="#";} type==lastType && length(line)>0 {print line;line=$0} type!=lastType {line=line$0} length(line)==0 {line=$0} END {print line}'
第一个sed命令在十六进制代码周围插入换行符,然后可以在所有以哈希开头的行上进行替换。可能有一个优雅的解决方案来重新合并线,但awk命令完成了这项工作。唯一的假设是不会有两个十六进制代码直接跟在彼此之后。如果是这样,则必须修改此步骤。