如何根据大小写替换文本?

时间:2017-03-27 05:20:22

标签: bash awk

以下是text.txt中的文字:

word1 Word2 word3

现在,我希望得到这个输出:

nword1 Nword2 nword3

到目前为止我做了什么:

sed -e  s/word1/nword1/gI text.txt
sed -e  s/word2/nword2/gI text.txt
sed -e  s/word3/nword3/gI text.txt

事情是我不知道哪个字有大写字母。因此我必须以小写形式输入“sed -e s / word3 / nword3 / gI text.txt”。

所以基本上,我想替换原始文本大写的单词。我怎样才能在bash脚本中执行此操作?

7 个答案:

答案 0 :(得分:1)

的Perl

perl -CSDA -plE 'BEGIN{$f=shift@ARGV;$t=lc(shift@ARGV)}s/(?i)\b($f)\b/$1=~m!^\p{Upper}!?ucfirst $t:$t/xge;' word nword

该解决方案不仅可以将N添加到word,还可以将任何给定的单词转换为另一个单词,保留原始单词大写。

更具可读性

perl -CSDA -plE '
   BEGIN{ $f = shift @ARGV; $t = lc(shift @ARGV) }
   s/ (?i) \b($f)\b/ $1 =~ m!^\p{Upper}! ? ucfirst $t : $t /xge;
' word nword

但建议你创建一个bash function,然后称之为casesubs

casesubs() {
    #usage: casesubs fromword toword
    perl -CSDA -plE 'BEGIN{$f=shift@ARGV;$t=lc(shift@ARGV)}s/(?i)\b($f)\b/$1=~m!^\p{Upper}!?ucfirst $t:$t/xge;' "$1" "$2"
}

现在您可以轻松地将其用作以下示例:

(
    text='abcword word Word word wordlen';
    echo "$text"
    casesubs word nword <<<"$text"

) | column -t #pretty printing

abcword  word   Word   word   wordlen  #orig
abcword  nword  Nword  nword  wordlen  #changed

该解决方案适用于任何utf8编码的Unicode,例如不仅[a-z]

(
    text='überJägermeister ÜBERJÄGERMEISTER'
    echo "$text"
    casesubs überJägermeister unterPIÑACOLÁDA <<<"$text"
) | column -t

输出

überJägermeister  ÜBERJÄGERMEISTER
unterpiñacoláda   Unterpiñacoláda

和文件也是如此,例如拥有内容

的文件capfile.txt
Ut debitis eveniet molestiae iusto quis ut. Est nemo dolores
error ipsum aut überJägermeister ÜBERJÄGERMEISTER. Numquam
itaque molestias ut iusto. Quia ut nobis expedita.

可以使用

casesubs überJägermeister unterPIÑACOLÁDA < capfile.txt

并获取

Ut debitis eveniet molestiae iusto quis ut. Est nemo dolores
error ipsum aut unterpiñacoláda Unterpiñacoláda. Numquam
itaque molestias ut iusto. Quia ut nobis expedita.

答案 1 :(得分:1)

或者我们可以使用简单的bash:

foo(x,y)

答案 2 :(得分:0)

您可以使用awk

awk '{for(i=1; i<NR; i++) { if ($i ~ /^[[:lower:]]/) {$i = "n"$i} else {$i = "N"$i}}}i' file

对于您的测试用例,它输出:

nword1 NWord2 nword3

无论你在每一行上有多少单词,它都能正常工作。

答案 3 :(得分:0)

AWK解决方案:

awk '{for(i=1;i<=NF;i++){printf "%s%s"FS,($i~/\<[[:lower:]]/)?"n":"N",tolower($i);}}' text.txt

输出:

nword1 Nword2 nword3 

解释

for(i=1;i<=NF;i++) - 遍历所有字段/列(即单词)

$i~/\<[[:lower:]]/ - 检查字段/单词是否以小写字母开头 \<gawk正则表达式运算符,它匹配单词开头的空字符串。例如,/\<away/匹配“away”但不匹配“stowaway”。

tolower($i) - 将单词转换为小写

答案 4 :(得分:0)

在awk中:

$ awk -v f="n" '
{
    for(i=1;i<=NF;i++) 
        sub(/^./, ((c=substr($i,1,1))~/[[:upper:]]/?toupper(f):f) tolower(c),$i)
} 1' file

当然,您也可以从echo进行管道传输。说明:

  • awk -v f="n" char to prepend被带入变量
  • for(i=1;i<=NF;i++)遍历记录中的每个单词
  • sub(/^./, (
  • 替换单词的第一个字符
  • (c=substr($i,1,1))~/[[:upper:]]/?toupper(f):f) tolower(c), word的第一个字符存储到c var,如果是大写,则从f生成大写字母并从c
  • 中删除字符 每个字
  • $i)

编辑赞成但未经测试。

答案 5 :(得分:0)

根据您向我们展示的样本输入,您只需要:

$ awk '{for (i=1;i<=NF;i++) $i=($i ~ /^[[:upper:]]/ ? "N" : "n") tolower($i)} 1' file
nword1 Nword2 nword3

如果这不是您所需要的,那么请编辑您的问题以显示更好地代表您的真实数据的示例输入。

答案 6 :(得分:-1)

我将概述你可以做的非正式恕我直言:

  1. 将文本文件#1读入变量,比如textfile1

    在for循环中:

    1. 逐行读取文本文件#2,在空格处分成两个变量pattern_to_match和replacement
    2. 在textfile1中查找pattern_to_match(使用不区分大小写的搜索)并将其存储在变量中,比如匹配
    3. 找出匹配的第一个字符是大写还是大写,并在变量upperCase中记住它
    4. 如果upperCase为true,则将变量替换为大写
    5. 替换为textfile1 pattern_to_match替换
  2. 这一切都可以在Bash / Sh中完成。