缩短过长的文本(使用 sed?)

缩短过长的文本(使用 sed?)

我有以下 .csv 文件示例

"0a","1a","Short text","abc"
"0b","1bx","Here is a very long text","def"
"0c","1cx","Short text again","ghij"

现在我希望第三列最多有 16 个字符。因此,“短文本”和“再次短文本”都可以。但“这是一段非常长的文本”应该是“这是一段非常长的文本”。更好的做法是“这是一段非常长的文本...”

这样,过长的文本(第 3 列)将被缩短并在末尾用“...”替换。

我找到了这个:

sed '/^.\{0,16\}$/!d' 

但这并不是我真正想要的,因为它只提取包含 0-16 个字符的整行。

也许你有更好的主意?

答案1

一个更好的想法——使用实际的 CSV 解析器:

#!/usr/bin/env python3
import csv
import sys

rd = csv.reader(sys.stdin)
wr = csv.writer(sys.stdout)

for row in rd:
    if len(row[2]) > 16:
        row[2] = row[2][:15] + "…"
    wr.writerow(row)

答案2

不是在 sed 中,而是在 perl 中。

您可以在 perl oneliner 中将检查添加到替换项前面,以应用替换仅有的如果字符串长度超过请求的大小。这里,在单向捕获中,不能捕获的限制是 13+3 个字符。

第二步,如果匹配成功,则用 13 个字符 + 3 个点替换整个字符串。

$ echo "12345678901234567" |perl -pe 'if (/^(.{13}).{4}/) { $_="$1..." }'
1234567890123...
$ echo "1234567890123456" |perl -pe 'if (/^(.{13}).{4}/) { $_="$1..." }'
1234567890123456

显然,sed 并不像看起来那么复杂,并且具有相同的逻辑,但有两个问题:1/ 检查字符串是否长于 16 个字符 2/ 如果是,则用前 13 个字符和 3 个点替换。

echo "12345678901234567" |sed '/^.\{16\}./ s/^\(.\{13\}\).\+/\1.../'
1234567890123...
echo "1234567890123456" |sed '/^.\{16\}./ s/^\(.\{13\}\).\+/\1.../'
1234567890123456

用真实的伪语言来启迪正则表达式:

if /^.{16}./
{
  s/^(.{13}).+/\1.../
}

答案3

sed 's/^\(".*",".*",".\{0,16\}\).*\(",.*\)$/\1\2/'

".*",".*",前 2 个 CVS 字段

".\{0,16\}打开双引号并最多包含第三个 CVS 字段的前 16 个字符

.*第 16 位直到最后角色

",.*\第三个 CVS 字段和其余 CVS 字段的结束双引号

\1第一组:\(".*",".*",".\{0,16\}\)

\2第二组:\(",.*\)

答案4

我相信您要寻找的是截断文本,而不是缩短它。
假设 您希望输出仅为第三列(最大长度为 16 个字符)
在这种情况下你可以使用命令(例=16)

例子

cut -c -16

要提取第三列,您也可以使用cut命令

例子

cut -d , -f 3

-d 是指定分隔符
-f 是选择哪个字段
或者您可以用作"分隔符来获取没有双引号的提取文本

cut -d \" -f 6

将它们与管道就可以了

cut -d \" -f 6 file.csv | cut -c -16

假设 您想要输出整个 .csv 文件(修改了第三列) Kees Trommel 的回答或者使用类似的脚本语言Python会是一种更简单的方法

相关内容