【发布时间】:2020-12-05 10:00:01
【问题描述】:
您将如何删除 x 个字符后的所有内容?例如,剪切 15 个字符后的所有内容并添加 ...。
This is an example sentence 应该变成This is an exam...
【问题讨论】:
标签: string bash shell string-length truncation
您将如何删除 x 个字符后的所有内容?例如,剪切 15 个字符后的所有内容并添加 ...。
This is an example sentence 应该变成This is an exam...
【问题讨论】:
标签: string bash shell string-length truncation
GnuTools head 可以使用字符而不是行:
head -c 15 <<<'This is an example sentence'
虽然考虑到head -c 只处理字节,所以这与UTF-8 变音符号ü 等多字节字符不兼容。
Bash 内置字符串索引的工作原理:
str='This is an example sentence'
echo "${str:0:15}"
输出:
This is an exam
最后还有一些适用于 ksh、dash、zsh 的东西……:
printf '%.15s\n' 'This is an example sentence'
甚至以编程方式:
n=15
printf '%.*s\n' $n 'This is an example sentence'
如果您使用的是 Bash,您可以直接将 printf 的输出分配给一个变量并保存一个子 shell 调用:
trim_length=15
full_string='This is an example sentence'
printf -v trimmed_string '%.*s' $trim_length "$full_string"
【讨论】:
cut 我猜也是一个选项,它也可以处理多字节字符
Awk 也可以做到这一点:
$ echo 'some long string value' | awk '{print substr($0, 1, 15) "..."}'
some long strin...
在 awk 中,$0 是当前行。 substr($0, 1, 15) 从 $0 中提取字符 1 到 15。尾随 "..." 附加三个点。
【讨论】:
使用cut:
echo "This is an example sentence" | cut -b1-15
This is an exam
【讨论】:
你可以试试:
echo 'some long string value' | sed 's/\(.\{15\}\).*/\1.../'
输出:
some long strin...
【讨论】:
如果您不关心 shell 的可移植性,您可以完全在 Bash 中使用 printf builtin 中的多个不同的 shell expansions 来完成此操作。这避免了对外部命令的攻击。例如:
trim () {
local str ellipsis_utf8
local -i maxlen
# use explaining variables; avoid magic numbers
str="$*"
maxlen="15"
ellipsis_utf8=$'\u2026'
# only truncate $str when longer than $maxlen
if (( "${#str}" > "$maxlen" )); then
printf "%s%s\n" "${str:0:$maxlen}" "${ellipsis_utf8}"
else
printf "%s\n" "$str"
fi
}
trim "This is an example sentence." # This is an exam…
trim "Short sentence." # Short sentence.
trim "-n Flag-like strings." # Flag-like strin…
trim "With interstitial -E flag." # With interstiti…
您也可以通过这种方式循环浏览整个文件。给定一个包含上述相同句子的文件(每行一个),您可以使用read builtin's default REPLY variable,如下所示:
while read; do
trim "$REPLY"
done < example.txt
这种方法是否更快或更容易阅读尚有争议,但它是 100% Bash 并且无需分叉或子外壳即可执行。
【讨论】:
-n、-e 或-E开始,则使用内置 printf 是更好的选择。
Todd 实际上有一个很好的答案,但是我选择对其进行一些更改以使功能更好并删除不必要的部分:p
trim() {
if (( "${#1}" > "$2" )); then
echo "${1:0:$2}$3"
else
echo "$1"
fi
}
在此版本中,较长字符串上的附加文本由第三个参数选择,最大长度由第二个参数选择,文本本身由第一个参数选择。
不需要变量:)
【讨论】:
trim(){ printf '%.*s' $2 "$1";}。如果你只想要 Bash,但速度更快;你可以这样做:printf -v trimmed_string '%.*s' $trim "$full_string"