在unix中用sed反转四个长度的字母
Posted
技术标签:
【中文标题】在unix中用sed反转四个长度的字母【英文标题】:Reverse four length of letters with sed in unix 【发布时间】:2018-04-02 21:01:01 【问题描述】:如何用sed
反转四个长度的字母?
例如:
the year was 1815.
转为:
the raey was 5181.
这是我的尝试:
cat filename | sed's/\([a-z]*\) *\([a-z]*\)/\2, \1/'
但它并没有按我的预期工作。
【问题讨论】:
单词由哪些字符组成?字母(小写/大写?)、数字?、下划线(例如:ab_c)等...你有 GNU sed 或其他版本吗? 在我的情况下,单词由小写字母、大写字母和数字组成。 我在 Ubuntu (cloud 9) 中有 GNU sed 【参考方案1】:不确定是否可以在所有情况下使用 GNU sed。如果_
没有出现在四个字母单词之前/之后,您可以使用
sed -E 's/\b([a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])\b/\4\3\2\1/gi'
\b
是单词边界,单词定义是任何字母或数字或下划线字符。所以\b
将确保只匹配整个单词而不是单词的一部分
$ echo 'the year was 1815.' | sed -E 's/\b([a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])\b/\4\3\2\1/gi'
the raey was 5181.
$ echo 'two time five three six good' | sed -E 's/\b([a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])\b/\4\3\2\1/gi'
two emit evif three six doog
$ # but won't work if there are underscores around the words
$ echo '_good food' | sed -E 's/\b([a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])\b/\4\3\2\1/gi'
_good doof
具有环视支持的工具适用于所有情况
$ echo '_good food' | perl -pe 's/(?<![a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])([a-z0-9])(?!=[a-z0-9])/$4$3$2$1/gi'
_doog doof
(?<![a-z0-9])
和 (?!=[a-z0-9])
分别为负向后瞻和负前瞻
可以缩短为
perl -pe 's/(?<![a-z0-9])[a-z0-9]4(?!=[a-z0-9])/reverse $&/gie'
它使用e
修饰符将Perl 代码放在替换部分。这种形式适合轻松改变要反转的单词长度
【讨论】:
你能解释一下/'gi'中的'i'是什么吗?而且我不必担心_所以不用担心。i
用于不区分大小写的匹配,否则需要[a-zA-Z0-9]
即使它在 4 个字母长度内也会失败。请与_123
核对,也许您不认为_
作为字母之一?
是的,OP 在 cmets 中提到 Word is constitute of lower case letters, upper case letters and numbers in my case
... 所以我的代码不会改变像 _123
或 1;2a
这样的词,而你的会【参考方案2】:
即使四个长度的字母包含_
s,也可能是最短的sed
解决方案。
sed -r 's/\<(.)(.)(.)(.)\>/\4\3\2\1/g'
【讨论】:
【参考方案3】:遵循 awk 可能会对您有所帮助。在 GNU awk 中对此进行了测试,并且仅使用提供的示例 Input_file
echo "the year was 1815." |
awk '
function reverse(val)
num=split(val, array,"");
i=array[num]=="."?num-1:num;
for(;i>q;i--)
var=var?var array[i]:array[i]
;
printf (array[num]=="."?var".":var);
var=""
for(j=1;j<=NF;j++)
printf("%s%s",j==NF||j==2?reverse($j):$j,j==NF?RS:FS)
'
【讨论】:
awk 似乎比 sed 更有效。但是在 sed 中可以吗? @Dante,可以在sed
完成,对不起,我不是 sed 专家,也许你可以等待人们在 sed 中提供解决方案。【参考方案4】:
这可能对你有用(GNU sed):
sed -r '/\<\w4\>/!b;s//\n&\n/g;s/^[^\n]/\n&/;:a;/\n\n/!s/(.*\n)([^\n])(.*\n)/\2\1\3/;ta;s/^([^\n]*)(.*)\n\n/\2\1/;ta;s/\n//' file
如果没有反转所需长度的字符串,则退出。
在所有必需的字符串前面加上换行符。
在模式空间 (PS) 的开头插入换行符。 PS分为两部分,第一行将包含当前正在反转的单词。其余部分将包含原始行。
要反转的单词的每个字符都插入到第一行的前面并从原始行中删除。当单词中的所有字符都被处理后,原来的单词就会消失,只存在边界换行符。然后将这些双换行符替换为第一行中的单词,并重复该过程,直到处理完所有单词。最后引入换行符来分隔工作行和原来的行被移除并打印PS。
注意此方法可用于反转可变字符串长度的字符串,即通过更改任何数字的第一个正则表达式字符串可以反转。两个长度之间的字符串也可以反转,例如/\<w2,4\>/
将更改 2 到 4 个字符长度之间的所有单词。
【讨论】:
【参考方案5】:这是一个经常出现的问题,所以有人创建了一个名为“rev”的 bash 命令。
echo "$(echo the | rev) $(echo year | rev) $(echo was | rev) $(echo 1815 | rev)"。
或
回显“那一年是 1815 年。” |转 | tr ' ' '\n' |塔克 | tr '\n' ' '
【讨论】:
以上是关于在unix中用sed反转四个长度的字母的主要内容,如果未能解决你的问题,请参考以下文章