我试图在textfile中搜索regex,而在匹配范围内只替换一个字符。我的问题是,我无法通过一些简单的方式来做到这一点。
示例源文件:
...
<br>
<a id="some shopitem" ref="#some shop item name 01 a" style="text-decoration:none;"><h3 style="background-color: #ccc;">blah blab hasdk sldk sasdas dasda sd</h3></a>
<table>
<td width="500">
....
我需要匹配regexp ref=\"#[[:alnum:] ]*\"
(ref =“#任何带空格的名称”)并在匹配中用“ - ”替换空格,但当然不要更改另一个空格或正则表达式匹配。 / p>
所以结果应该是这样的:
....
<br>
<a id="some shopitem" href="#some-shop-item-name-01-a" style="text-decoration:none;"><h3 style="background-color: #ccc;">blah blab hasdk sldk sasdas dasda sd</h3></a>
<table>
<td width="500">
....
甚至可以在bash中的单行命令中没有某种脚本的情况下这样做吗?有没有办法如何替换组中的空格?类似于sed -r s/ref=\"#([[:alnum:] ]*\)/(\1s/ /-/g)/g'
?
答案 0 :(得分:0)
perl解决方案:
perl -pe 's/(ref="#)([\w\s]+)(")/ ($x,$y,$z)=($1,$2,$3); $y =~ s{\s}{-}g; $x.$y.$z /eg'
对于可以出现在引用名称(下划线,制表符,其他一些空白字符)中的内容稍微宽容一点
答案 1 :(得分:0)
甚至可以在bash中的单行命令中没有某种脚本的情况下这样做吗?
你的问题在某种程度上引发了我这样做的野心......!
varfile=SOURCEFILE && varsubstfile=RESULTFILE && IFS=' ' read -a repl <<< $(sed -r 's/(.*)(ref="#.*?")( .*)/\2/;tx;d;:x' $varfile | sed -e 's/\ /\-/g' | sed ':a;N;$!ba;s/\s/ /g') && for i in "${!repl[@]}"; do needle["$i"]=$(sed 's/\-/\ /g' <<< "${repl["$i"]}"); done && cp $varfile $varsubstfile && for i in "${!needle[@]}"; do sed -ir "s/${needle[i]}/${repl[i]}/g" $varsubstfile; done && unset needle && unset repl && less $varsubstfile && unset varfile && unset varsubstfile
SOURCEFILE
是您的源文件,RESULTFILE
是输出写入的文件的名称,因此根据您的需要更改它们。
嗯......这是一个剧本,但它是一个(该死的巨大的)单行:)
我认为整个文件中出现ref="#.*"
的次数更多,否则它会更短(虽然我不再记得更短的版本了)。
...我真的希望这适用于你的* nix系统:D
<小时/> 万一你想知道这件事是做什么的,这里有一个解释:
varfile=SOURCEFILE && #set variable for the sourcefile
varsubstfile=RESULTFILE && #set variable for the resultfile
IFS=' ' read -a repl <<< #we're going to read multiple values into an array "repl"
#delimited by a space
$(
#grab only the second capture group (ref="#.*?")
sed -r 's/(.*)(ref="#.*?")( .*)/\2/;tx;d;:x' $varfile |
sed -e 's/\ /\-/g' | #replace every space in (ref="#.*?") with a dash
sed ':a;N;$!ba;s/\s/ /g' #replace newlines with a space
#when there is more than one occurence sed will delimit them with a newline
#but i set a space as the delimiter for the read operation,
#thus the last replacement
) &&
#we now have every needed replacement-string in an array called "repl"
for i in "${!repl[@]}"; do #iterate over every value in the array we just read
needle["$i"]=$(sed 's/\-/\ /g' <<< "${repl["$i"]}"); #replace dashes with spaces and store in a new variable
done &&
#and now every original string, the needle we are going to search for
#is stored in another array
cp $varfile $varsubstfile && #copy sourcefile to resultfile
for i in "${!needle[@]}"; do #for every string we are going to replace
sed -ir "s/${needle[i]}/${repl[i]}/g" $varsubstfile; #... we replace it!
done
#technically we're done here
#but i like to clean up afterwards and show the result with less
unset repl && less $varsubstfile && unset varfile && unset varsubstfile