当字符串中存在多个字符时,如何仅更改该字符?

当字符串中存在多个字符时,如何仅更改该字符?

我需要编写一个脚本将电话号码从 123-123-1234 转换为 (123) 123-1234 和 1231231234。我可以使用 tr 命令更改连字符的所有实例,但如何仅更改两个中的一个?我用这段代码做了第二部分

echo "Enter phone number (xxx-xxx-xxxx)"
read phone
echo $phone | cat > phone
tr -d "-" < phone

我知道有更好的方法,但我是新学生,还不知道,提前感谢您的帮助

答案1

标题(“当字符串中存在多个字符时,如何更改该字符?”)是您尝试的解决方案,但实际问题在问题正文中进行了解释。比较XY问题。我的回答针对的是身体。


IFS=- read n1 n2 n3

这将使用用户输入的片段填充n1,n2和变量;n3分别:

  • 在第一个之前-
  • 在第一个-和第二个之间-
  • 在第二个之后-(包括剩余的-字符,如果有的话)。

然后你可以用printf你想要的任何格式打印它们,例如

printf '(%s) %s-%s\n' "$n1" "$n2" "$n3"
printf '%s%s%s\n' "$n1" "$n2" "$n3"

你可能想要对你所接受的事物持自由态度并且不需要严格的格式。 shell 函数的示例:

get_phone_number() {
   IFS= read -rp "Enter phone number (10 digits; additional dashes, spaces, whatever allowed): " p || return 1
   # remove non-digits
   p="$(tr -dc '0123456789' <<< "$p")"
   # check if there is 10 of them
   if [ "${#p}" -ne 10 ]; then
      echo "Wrong number of digits. Aborting." >&2; return 2
   else
      n1="${p:0:3}"
      n2="${p:3:3}"
      n3="${p:6:4}"
   fi
}

调用get_phone_number.如果函数成功,则使用$n1,$n2$n3with printf(如上)或以任何您想要的方式。

答案2

GNUsed允许指定应替换(一行中)出现的模式:

第一个(默认)

echo AAAAA | sed 's/A/X/'
XAAAA

全部

echo AAAAA | sed 's/A/X/g'
XXXXX

第 i 个

echo AAAAA | sed 's/A/X/3'
AAXAA

要使用此方法专门针对您的问题,您需要进行两项修改sed:1) 更改行的开头 ( ^) 以添加左括号,2) 将第一个破折号替换为右括号和一个空格。

echo 123-123-1234 | sed 's/^/(/;s/-/) /'
(123) 123-1234

或者,sed允许匹配模式并通过将模式括在括号中来保存它们(按出现次数)。在输出字符串中,您可以通过编号来调用它们:

echo 123-123-1234 | sed 's/\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)/(\1) \2-\3/'
(123) 123-1234

这里[0-9]匹配 0 到 9 之间的数字,\+表示前一组出现一次或多次(GNU 扩展为sed),\(<pattern>\)并将保存模式并为其指定索引号(第一个从 1 开始,依此类推)。因此\([0-9]\+\)-将匹配一个或多个数字,后跟破折号,并记住数字部分。

在输出中\1打印匹配中第一个保存的模式(即[0-9]\+......破折号之前的一个或多个数字。然后我们只需使用三个保存的数字组并根据需要格式化它们。

答案3

您意识到您正在创建一个名为phone对吗?而且管道进入echocat没有意义的,你可以(但不应该)这样做echo "$phone" > phone


我为您提出了以下解决方案。它可能不是最短的方法,但它会起作用:

#!/bin/bash

read -rp "Enter phone number (xxx-xxx-xxxx): " p

area_code=${p:0:3}
prefix=${p:4:3}
line=${p:8:4}

printf '%s\n%s\n' \
"($area_code) ${prefix}-${line}" \
"${area_code}${prefix}${line}"

Read 可以提示用户输入,这样我们就可以消除echo/read组合。
然后我们使用参数扩展拉出电话号码的三个部分,并以您需要的两种格式打印它们。

注意:这不会进行任何类型的健全性检查,因此用户可以提供虚假输入,并且他们将获得虚假输出。

相关内容