如何在 bash 中创建数字符号

如何在 bash 中创建数字符号

我正在尝试编写一个代码,将任何给定的单词转换为其数字名称。

例如:国际化= i18n(第一个字符+中间的字符数+最后一个字符)

我找到了如何查找第一个和最后一个字符,并且知道如何查找数字部分,但我不知道如何将数字放在第一个和最后一个字符之间。

我用来获取数字部分的代码是:

cut -c 2- | rev | cut -c 2- | rev | tr -d [:space:]| wc -c 

我用来获取第一个和最后一个字符的代码:

awk -F "" '{print $1,$NF}'

答案1

尽管我发现使用awk空字段分隔符有些“创新”,但我认为最简单的解决方案只是您的解决方案的一个小扩展:

awk -F "" '{print $1 (NF-2) $NF}'

当然,这只适用于三个或更多字母的单词。处理一般情况:

awk -F "" '{if (NF>2) print $1 (NF-2) $NF; else print $0}'

作为解释:

  • 通过使用 将字段分隔符设置为“空” -F "",输入将在每个字符后拆分为多个字段,即输入的每个字符都被视为一个单独的“字段”,可通过$nin访问的单独“字段”awk表达式(与n是范围从 1 到NF) 的字段编号。顺便说一句,GNU Awk 用户指南明确指出提供此类用例作为示例,所以我纠正了我之前对使用空 FS 的担忧。不过,请注意手册中说“这是一个常见的扩展;POSIX 标准并未指定它”。
  • if字段数(即此处的字符数)大于 2,则打印第一个字段/字符 ( $1)、求值表达式 ( NF-2)(相当于第一个和最后一个之间的字符数)以及最后一个字段/字符( $NF)。请注意,print此处使用的调用不会在各个输出标记之间产生空格;仅当用逗号而不是空格分隔参数时才会发生这种情况(请参阅例如 GNU Awk 用户指南)。
  • else只需打印整个输入表达式,可以通过以下方式访问$0

请注意,如果我们错误地输入了两个字符的输入,例如 at,对于第一个代码示例,我们会得到不需要的(但形式上正确的)输出a0t(因为在这种情况下,第一个和最后一个之间有零个字符)。

另请注意,这一点很重要,如果您为此调用提供包含前导或尾随空格的字符串awk(例如 in )echo " hello" | awk <etc.>,那么该前导/尾随空格将被视为第一个/最后一个字符,从而产生不需要的行为!

答案2

在 ksh93、bash 或 zsh 中:

numeronym() {
  (( ${#1} > 2 )) || return
  printf '%s%d%s\n' "${1:0:1}" "$(( ${#1} - 2 ))" "${1: -1:1}"
}

这通过打印第一个字母(字符数减 2)和最后一个字母来处理第一个(唯一)参数。

答案3

另一个 awk 解决方案:

awk '{l=length($1); print substr($1,1,1) l-2 substr($1,l,1)}'
  • l=length($1)- 将l变量设置为字符串的长度(假设输入字符串位于第一列并且不包含空格)
  • substr($1,1,1)- (列#、起始点、结束点)因此打印第 1 列,从位置 1 开始,并打印 1 个字符。
  • l-2- 字符串长度减 2
  • substr($1,l,1)- 从位置l(字符串长度)开始打印第 1 列并打印 1 个字符。

答案4

可移植到许多 shell:

a=internationalization;
if [ "${#a}" -gt 2 ]; then 
    a="${a%"${a#?}"}$((${#a}-2))${a#"${a%?}"}";
fi
printf '%s\n' "${a}"

作为一个函数(可移植性稍差):

numeronym() {  a="$1";
               if [ "${#1}" -gt 2 ]; then 
                    a="${a%"${a#?}"}$((${#a}-2))${a#"${a%?}"}";
               fi;
               printf '%s\n' "${a}";
            }

称其为:

$ numeronym internationalization
i18n

如果必须是 awk:

$ echo internationalization |
      awk '{ print (NF>2) ? $1 NF-2 $NF : $0 }' FS=''

i18n

相关内容