Renga Asked: 2022-11-25 00:07:34 +0800 CST2022-11-25 00:07:34 +0800 CST 2022-11-25 00:07:34 +0800 CST 打印文件中的第一个和最后一个非空(或非空白)行 772 我想打印文件中的第一行和最后一行非空行或非空白行,最好使用sedor awk。 输入文件: 123 345 456 087 er 56 32 78 注意后面有一个空行32 78。 期望的输出: 123 345 32 78 text-processing 3 个回答 Voted Best Answer Kusalananda 2022-11-25T01:50:49+08:002022-11-25T01:50:49+08:00 请注意,由于修改了问题中的文本,我在这里回答了两个问题: 我们如何从文件中输出第一行和倒数第二行(最初的问题包含“倒数第二行”的措辞)? 我们如何输出第一行和最后一行非空非空行? 使用ed编辑器,它的行寻址比 更灵活sed,主要是因为将所有数据读入内存而不是一次读取一行: $ printf '%s\n' 1p '$-1p' Q | ed -s file 123 345 32 78 这会在退出前打印输入文件的第一行和倒数第二行。倒数第二行的地址是 using $-1,可以缩短为 just $-。 如果我们不知道末尾正好有一个空行,我们可以从第 1 行向后搜索包含某些内容的行并打印: $ printf '%s\n' 1p '?[[:graph:]]?p' Q | ed -s file 123 345 32 78 使用sed: $ sed -n -e 1p -e '${ g; p; }' -e h file 123 345 32 78 这首先关闭每行的默认输出-n。然后打印第一行。所有行都使用保存到保留空间h,在最后一行,我们使用获取保留空间g并打印它。由于最后两个表达式的顺序,这将打印倒数第二行。 通过一个小的修改,我们可以将其更改为输出最后一个非空行,无论它是否是倒数第二行: $ sed -n -e 1p -e '/[[:graph:]]/h' -e '${ g; p; }' file 123 345 32 78 使用 和 的组合grep,sed我们可以先过滤掉所有空行或看起来空的行,然后只输出第一行和最后一行: $ grep '[[:graph:]]' file | sed -n -e 1p -e '$p' 123 345 32 78 请注意,这也会输出第一个非空行,即使这不是原始数据中的第一行。 AdminBee 2022-11-25T05:49:51+08:002022-11-25T05:49:51+08:00 以下 awk程序将执行此操作: awk 'NF{last=$0; if (!c++) print;} END {if (c>1) print last}' file.txt awk默认情况下将输入行拆分为“空白”处的字段,即连续运行的空格和制表符。字段数存储在NF. 如果一行完全为空,或仅由空格组成,NF则为零。 如果程序遇到真正且视觉上非空的行,即NF非零且计算结果为true,它会将行内容存储在缓冲区last中。如果这是第一个这样的行(计数器变量c将被取消设置并求值为false),它会打印当前行。在任何情况下,它都会增加c,因此对于第一个非空行,这种情况只会发生一次。 最后, if 打印last最后一个非空行的内容,但仅限于 ifc>1,因此如果只有一行非空,则该行将只打印一次。如果所有行都是空的,则计算结果为 0,即使在子句c中也不会打印任何内容。END MiniMax 2022-11-25T07:39:01+08:002022-11-25T07:39:01+08:00 sed -n '/^$/d; p; :a; n; /^$/!h; $!ba; g; /^$/!p' file.txt 测试文件内容: ==> file_1.txt <== 123 345 456 087 er 56 32 78 ==> file_2.txt <== 123 345 456 087 er 56 32 78 ==> file_3.txt <== 123 345 456 087 er 56 32 78 ==> file_4.txt <== 123 345 456 087 er 56 32 78 ==> file_5.txt <== 123 345 测试 for f in file_{1..5}.txt; do echo "==> $f <==" sed -n '/^$/d; p; :a; n; /^$/!h; $!ba; g; /^$/!p' "$f" done 输出: ==> file_1.txt <== 123 345 32 78 ==> file_2.txt <== 123 345 32 78 ==> file_3.txt <== 123 345 32 78 ==> file_4.txt <== 123 345 32 78 ==> file_5.txt <== 123 345
请注意,由于修改了问题中的文本,我在这里回答了两个问题:
我们如何从文件中输出第一行和倒数第二行(最初的问题包含“倒数第二行”的措辞)?
我们如何输出第一行和最后一行非空非空行?
使用
ed
编辑器,它的行寻址比 更灵活sed
,主要是因为将所有数据读入内存而不是一次读取一行:这会在退出前打印输入文件的第一行和倒数第二行。倒数第二行的地址是 using
$-1
,可以缩短为 just$-
。如果我们不知道末尾正好有一个空行,我们可以从第 1 行向后搜索包含某些内容的行并打印:
使用
sed
:这首先关闭每行的默认输出
-n
。然后打印第一行。所有行都使用保存到保留空间h
,在最后一行,我们使用获取保留空间g
并打印它。由于最后两个表达式的顺序,这将打印倒数第二行。通过一个小的修改,我们可以将其更改为输出最后一个非空行,无论它是否是倒数第二行:
使用 和 的组合
grep
,sed
我们可以先过滤掉所有空行或看起来空的行,然后只输出第一行和最后一行:请注意,这也会输出第一个非空行,即使这不是原始数据中的第一行。
以下
awk
程序将执行此操作:awk
默认情况下将输入行拆分为“空白”处的字段,即连续运行的空格和制表符。字段数存储在NF
. 如果一行完全为空,或仅由空格组成,NF
则为零。NF
非零且计算结果为true
,它会将行内容存储在缓冲区last
中。如果这是第一个这样的行(计数器变量c
将被取消设置并求值为false
),它会打印当前行。在任何情况下,它都会增加c
,因此对于第一个非空行,这种情况只会发生一次。last
最后一个非空行的内容,但仅限于 ifc>1
,因此如果只有一行非空,则该行将只打印一次。如果所有行都是空的,则计算结果为 0,即使在子句c
中也不会打印任何内容。END
测试文件内容:
测试
输出: