我试图在文本文件中搜索正则表达式,而不是在匹配范围内只用另一个字符替换一个字符。我的问题是,我无法通过某种简单的方式做到这一点。
示例源文件:
...
<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">
....
在那里我需要匹配正则表达式ref="#[[:alnum:] ]*"
(ref="#whatever 名称与空格"),并将空格替换为"-",但当然不要更改另一个空格或正则表达式匹配。
所以结果应该看起来像这样:
....
<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'
?
一个perl解决方案:
perl -pe 's/(ref="#)([ws]+)(")/ ($x,$y,$z)=($1,$2,$3); $y =~ s{s}{-}g; $x.$y.$z /eg'
它对引用名称中可以出现的内容稍微宽松一些(下划线、制表符、其他一些空格字符)
甚至有可能在没有某种脚本的情况下仅在 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