Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 使用基于sed的反向引用的另一个字符串替换字符串_Regex_Linux_Sed - Fatal编程技术网

Regex 使用基于sed的反向引用的另一个字符串替换字符串

Regex 使用基于sed的反向引用的另一个字符串替换字符串,regex,linux,sed,Regex,Linux,Sed,我正在尝试转换预定义的字符串%c#,其中可以是带有另一个字符串的某个数字。问题是另一个字符串的长度必须被截断为#字符数 理想情况下,这些命令集可以工作: FORMAT="%c10" LAST_COMMIT="5189e42b14797b1e36ffb7fc5657c7eea08f1c0f" echo $FORMAT | sed "s/%c\([0-9]\+\)/${LAST_COMMIT:0:\1}/g" 但显然\1上存在语法错误。您可以将其替换为一个数字,以查看我试图获得的输出 我愿意使用除

我正在尝试转换预定义的字符串
%c#
,其中
可以是带有另一个字符串的某个数字。问题是另一个字符串的长度必须被截断为
#
字符数

理想情况下,这些命令集可以工作:

FORMAT="%c10"
LAST_COMMIT="5189e42b14797b1e36ffb7fc5657c7eea08f1c0f"
echo $FORMAT | sed "s/%c\([0-9]\+\)/${LAST_COMMIT:0:\1}/g"
但显然\1上存在语法错误。您可以将其替换为一个数字,以查看我试图获得的输出

我愿意使用除
sed
之外的其他程序来实现这一点,但理想情况下,它应该是大多数linux安装都非常原生的程序

谢谢

这是我的想法

echo ${LAST_COMMIT} | head -c $(echo ${FORMAT} | sed -e 's/%c//')
使用
sed
获取数字,并使用
头获取第一个字符

EDIT1

这可能更好

echo ${LAST_COMMIT} | head -c $(echo ${FORMAT} | sed -e 's/%c\([0-9]\+\)/\1/')
EDIT2

我写剧本是因为太难理解了。请试试这个

$ cat sample.sh

#!/bin/bash

FORMAT="%b-%t-%c10-%c5"
LAST_COMMIT="5189e42b14797b1e36ffb7fc5657c7eea08f1c0f"

## List numbers
lengths=$(echo ${FORMAT} | sed -e "s/%[^c]//g" -e "s/-//g" -e "s/%c/ /g")

## Substitute %cXX to first XX characters of LAST_COMMIT
for n in ${lengths}
do
  to_str=$(echo ${LAST_COMMIT:0:${n}})
  FORMAT=$(echo ${FORMAT} | sed "s/%c${length}/${to_str}/")
done

## Print result
echo ${FORMAT}
这就是结果

$ ./sample.sh
%b-%t-5189e42b1410-5189e5
这也是单行命令(内容相同,但太长太硬)

这是我的主意

echo ${LAST_COMMIT} | head -c $(echo ${FORMAT} | sed -e 's/%c//')
使用
sed
获取数字,并使用
头获取第一个字符

EDIT1

这可能更好

echo ${LAST_COMMIT} | head -c $(echo ${FORMAT} | sed -e 's/%c\([0-9]\+\)/\1/')
EDIT2

我写剧本是因为太难理解了。请试试这个

$ cat sample.sh

#!/bin/bash

FORMAT="%b-%t-%c10-%c5"
LAST_COMMIT="5189e42b14797b1e36ffb7fc5657c7eea08f1c0f"

## List numbers
lengths=$(echo ${FORMAT} | sed -e "s/%[^c]//g" -e "s/-//g" -e "s/%c/ /g")

## Substitute %cXX to first XX characters of LAST_COMMIT
for n in ${lengths}
do
  to_str=$(echo ${LAST_COMMIT:0:${n}})
  FORMAT=$(echo ${FORMAT} | sed "s/%c${length}/${to_str}/")
done

## Print result
echo ${FORMAT}
这就是结果

$ ./sample.sh
%b-%t-5189e42b1410-5189e5
这也是单行命令(内容相同,但太长太硬)


$LAST_COMMIT
的值在运行
sed
之前进行插值,因此还没有可返回的反向引用。GNU
sed
中有一个
/e
扩展,它支持类似的东西,但我只想使用一个功能稍强的工具

perl -e '$fmt = shift; $fmt=~ s/%c(\d+)/%.$1s/g; printf("$fmt\n", @ARGV)' '%c10' "$LAST_COMMIT"

当然,如果您可以放弃自己的特殊格式字符串说明符,并切换到与
printf
兼容的格式字符串,只需直接使用
printf
shell命令。

sed
运行之前插入
$LAST\u COMMIT
的值,因此,目前还没有可供参考的反向参考。GNU
sed
中有一个
/e
扩展,它支持类似的东西,但我只想使用一个功能稍强的工具

perl -e '$fmt = shift; $fmt=~ s/%c(\d+)/%.$1s/g; printf("$fmt\n", @ARGV)' '%c10' "$LAST_COMMIT"

当然,如果您可以放弃自己的特殊格式字符串说明符,并切换到与
printf
兼容的格式字符串,只需立即使用
printf
shell命令。

如果您可以更改格式字符串的格式,那么
printf
可以是一个选项
printf“%.10s”“5189e42b14797b1e36ffb7fc5657c7eea08f1c0f“
你想写一个漂亮的git日志输出吗?是的。好的,这个主意很有趣。我可以分两步来做。1.将%c替换为%。#s然后执行替换。其他人能一步到位吗?@nhahdh似乎无法让您的解决方案处理多个替换,即动态地将多个参数传递给printf。帮助?:)它适用于我
printf“%.10s%.10s”“5189e42b14797b1e36ffb7fc5657c7eea08f1c0f”“abcdef5189e42b14797b1e36ffb7fc5657c7eea08f1c0f”
输出
5189e42b14 abcdef5189
。不过,我并不完全确定平台的差异。如果您可以更改格式字符串的格式,那么
printf
可以是一个选项
printf“%.10s”“5189e42b14797b1e36ffb7fc5657c7eea08f1c0f”
您正在尝试编写一个漂亮的git日志输出吗?是的。好的,这个主意很有趣。我可以分两步来做。1.将%c替换为%。#s然后执行替换。其他人能一步到位吗?@nhahdh似乎无法让您的解决方案处理多个替换,即动态地将多个参数传递给printf。帮助?:)它适用于我
printf“%.10s%.10s”“5189e42b14797b1e36ffb7fc5657c7eea08f1c0f”“abcdef5189e42b14797b1e36ffb7fc5657c7eea08f1c0f”
输出
5189e42b14 abcdef5189
。不过,我并不完全确定平台的不同。只是想澄清一下。这将替换所有出现的
%c
,还是只替换第一个?“全部”不是必需的,而是首选项。“s/%c/”将只删除第一个“%c”。因此,“s/%c([0-9]\+)/\1/”可能更好。我编辑了我的回答,注意到格式将是很多东西
FORMAT=“%b-%t-%c10-%c5”
。其他的一切都会处理好,最终只剩下一个字符串,其中只有
%c
,您需要哪个%c
echo${FORMAT}sed-e的/^.*%c\([0-9]\+\)-%c\([0-9]\+\).$/\1/g'
将返回%c的第一个数字(即返回10)。和
echo${FORMAT}sed-e的/^.*%c\([0-9]\+\)-%c\([0-9]\+\).$/\2/g'
将返回第二个数字%c(即返回5)。我的问题不同。给定
LAST\u COMMIT=“asdfghjkl”
FORMAT=“%c2-%c5”
代码应以asdfg
的形式返回
。不必是一行,只是为了清楚。这将替换所有出现的
%c
,还是只替换第一个?“全部”不是必需的,而是首选项。“s/%c/”将只删除第一个“%c”。因此,“s/%c([0-9]\+)/\1/”可能更好。我编辑了我的回答,注意到格式将是很多东西
FORMAT=“%b-%t-%c10-%c5”
。其他的一切都会处理好,最终只剩下一个字符串,其中只有
%c
,您需要哪个%c
echo${FORMAT}sed-e的/^.*%c\([0-9]\+\)-%c\([0-9]\+\).$/\1/g'
将返回%c的第一个数字(即返回10)。和
echo${FORMAT}sed-e的/^.*%c\([0-9]\+\)-%c\([0-9]\+\).$/\2/g'
将返回第二个数字%c(即返回5)。我的问题不同。给定
LAST\u COMMIT=“asdfghjkl”
FORMAT=“%c2-%c5”
代码应以asdfg
的形式返回
。不必只有一行。您有一个语法错误-
$(…)
${…}
之间存在显著差异。此外,一般来说,在没有正确引用的情况下,不应使用
echo
。最后,所有