任务是在具有5个或更少字符的单词中反转所有字母(a-zA-Z)。
编辑:让我们假设单词是一个不间断的英文字母序列。
(字母:ASCII范围A-Z&& a-z)
示例:
输入:"One ring to rule them all, one ring to find them, One ring to bring them all and in the darkness bind them."
输出:"enO gnir ot elur meht lla, eno gnir ot dnif meht, enO gnir ot gnirb meht lla dna ni eht darkness dnib meht."
我已经能够编写这个脚本了,但是它用带有特殊字符的单词来翻译,例如{,。},它们不应该被反转。
#!/bin/bash
word_length=0
touch tmp
for word in $(cat ./TEXT)
do
word_length=$(echo -n $word | wc -c )
if [ $word_length -le 5 ]
then
echo -n $word | rev >> tmp
echo -n " " >> tmp
else
echo -n $word >> tmp
echo -n " " >> tmp
fi
done
cat tmp > TEXT
echo " " >> TEXT
rm -rf tmp
此脚本的输出:
"enO gnir ot elur meht ,lla eno gnir ot dnif ,meht enO gnir ot gnirb meht lla dna ni eht darkness dnib .meht"
您可以看到{,。}位于错误的位置。
答案 0 :(得分:2)
您可以使用此awk
代码:
awk 'function revw(wrd) {
if (wrd ~ /[^a-zA-Z]+[a-zA-Z]+$/ || length(wrd) > 5)
return wrd
nw = wrd
sub(/^[a-zA-Z]+/, "", nw)
sub(/[^a-zA-Z]+$/, "", wrd)
rw = ""
for (j=length(wrd); j>0; j--)
rw = rw substr(wrd, j, 1)
return rw nw
}
{
line = ""
for (i=1; i<=NF; i++)
line = line revw($i) (i==NF ? "" : OFS)
print line
}' file
enO gnir ot elur meht lla, eno gnir ot dnif meht, enO gnir ot gnirb meht lla dna ni eht darkness dnib meht.
答案 1 :(得分:1)
for word in $(cat ./TEXT)
,
看起来你可能会迭代输入的单词,
但是Bash对单词的定义与你预期的不同。
在上面的陈述中,
Bash执行分词,
但这只是意味着按IFS
的值进行分割。
默认情况下,此值是空白字符序列。
这意味着标点符号将成为单词的一部分。
任务是在具有5个或更少字符的单词中反转所有字母(a-zA-Z)。
对于强大的解决方案, 考虑这个算法:
word
初始化为空字符串c
c
是一封信,请将其附加到word
word
超过4个字符,请将其打印word
不为空,则将其反转word
重置为空c
word
,以确保打印出最后一个单词使用纯Bash:
#!/usr/bin/env bash
s=$(cat ./TEXT)
print_reverse() {
local w=$1
local i
reversed=
for ((i = 0; i < ${#w}; i++)); do
reversed=${w:i:1}$reversed
done
printf "$reversed"
}
print_word() {
local w=$1
if [ ${#w} -gt 4 ]; then
printf "$w"
elif [ "$w" ]; then
print_reverse "$w"
fi
}
word=
for ((i = 0; i < ${#s}; i++)); do
c=${s:i:1}
case "$c" in
[a-zA-Z]) word=$word$c ;;
*)
print_word "$word"
word=
printf "$c"
;;
esac
done
print_word "$word"
答案 2 :(得分:0)
您必须将.
和,
与您的单词分开。
你可以:
cat ./TEXT
更改第一个sed -r 's/([,.])/ \1/g' ./TEXT
,在这些字符sed -r 's/ ([,.])/\1/g' ./TEXT
删除之前添加的空白区域(在你的例子中,你的TEXT文件有一个逐字逐句,但我接受了这个假设,你将会纠正这个)但是,这将仅限于像,.':;
这样的sed中放入的字符,如果出现新字符,则必须更改脚本
除此之外,为什么限制5个字符来反转一个单词?在你的例子中,黑暗并没有因此而逆转。
答案 3 :(得分:0)
另一个gawk
gawk -v RS='[^a-zA-Z]' 'function rev(x,rx) {n=split(x,a,"");
while(n) rx=rx a[n--];
return rx}
{printf "%s", (length()>5?$0:rev($0)) RT}' file
enO gnir ot elur meht lla, eno gnir ot dnif meht, enO gnir ot gnirb meht lla dna ni eht darkness dnib meht.
答案 4 :(得分:0)
另一种bash
方法,请注意此代码会将don't
中的撇号转换为tnod'
: -
while read line
do
printf "$line\n"
for word in $line
do
for (( i = ${#word}; i >= 0; i-- ))
do
if [[ "${word:$i:1}" =~ '[[:alpha:]]' ]]
then
printf "${word:$i:1}"
else
symb="${word:$i:1}"
fi
done
printf "${symb} "
done
printf "\n"
done < TEXT
答案 5 :(得分:0)
使用perl
$ cat ip.txt
"One ring to rule them all,
one ring to find them,
One ring to bring them all and in the darkness bind them."
O'Donnell 1234 there's pre-existing
$ perl -F'/([^a-z])/i' -ane '
print map {$_ = length()<6 && /[a-z]/i ? reverse : $_} @F' ip.txt
"enO gnir ot elur meht lla,
eno gnir ot dnif meht,
enO gnir ot gnirb meht lla dna ni eht darkness dnib meht."
O'Donnell 1234 ereht's erp-existing
-F'/([^a-z])/i'
使用非字母作为字段分隔符,使用()
表示字段分隔符也会与字段一起保存在@F
数组中
map
用于转换数组的每个元素length()<6 && /[a-z]/i
条件选择小于长度为6的单词并忽略字段分隔符reverse
将在标量上下文中反转字符串