我有以下 .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
会是一种更简单的方法