我需要解析
utmpdump /var/log/wtmp
返回的行。它们的格式如下:
[8] [13420] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:18:29,836564+00:00]
[7] [13611] [ts/3] [john ] [pts/3 ] [192.168.1.38 ] [192.168.1.38 ] [2024-07-22T11:21:30,065856+00:00]
[8] [13611] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:21:41,814051+00:00]
特点是:
[]
,\0
),如何将这样的一行解析为 8 个
char*
变量,其中 sscanf
具体是什么?我无法解决的问题是如何修剪尾随空格,同时允许 []
之间的字符串长度变化。还可以用sscanf
吗?
我有一个没有
sscanf
的可行解决方案,但是这个解决方案必须专门使用 sscanf
来完成。在 sscanf
解析之后修剪空格是一种备份解决方案,但我尝试通过 sscanf
完全解析来完成此操作。
使用
"%n"
确定扫描部分的偏移。
*scanf()
不喜欢形成 0 长度的字符串,因此在扫描列时,请将 [
视为字段的一部分,以确保字段中至少有 1 个字符。 后来,启动字段1通过了'['
。
#include <stdio.h>
char *cut_up_line(char *offset[8], char * line) {
for (int i = 0; i < 8; i++) {
//int field_start;
int field_end;
int column_end = 0;
// If possible for the line to include unusually white-spaces,
// adjust format to include them: "%*[^] \t\r\v\f]%n ] %n"
sscanf(line, "%*[^] \t]%n ] %n", &field_end, &column_end);
if (column_end == 0) {
// debug: printf("-%d <%s>\n", i, line);
return NULL;
}
// Maybe add test here that *line is a '['.
offset[i] = line + 1;
line[field_end] = '\0';
line += column_end;
// debug: printf("+%d <%s>\n", i, offset[i]);
}
return line;
}
void test(char *line) {
printf("<%s>\n", line);
char *field[8];
if (cut_up_line(field, line) == NULL) {
printf("** Failed **\n");
} else {
for (int i = 0; i < 8; i++) {
printf(" %d:<%s>\n", i, field[i]);
}
}
}
int main() {
char s1[] = "[8] [13420] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:18:29,836564+00:00]";
char s2[] = "[7] [13611] [ts/3] [john ] [pts/3 ] [192.168.1.38 ] [192.168.1.38 ] [2024-07-22T11:21:30,065856+00:00]";
char s3[] = "[8] [13611] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:21:41,814051+00:00]";
test(s1);
test(s2);
test(s3);
}
输出
<[8] [13420] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:18:29,836564+00:00]>
0:<8>
1:<13420>
2:<>
3:<>
4:<pts/3>
5:<>
6:<0.0.0.0>
7:<2024-07-22T11:18:29,836564+00:00>
<[7] [13611] [ts/3] [john ] [pts/3 ] [192.168.1.38 ] [192.168.1.38 ] [2024-07-22T11:21:30,065856+00:00]>
0:<7>
1:<13611>
2:<ts/3>
3:<john>
4:<pts/3>
5:<192.168.1.38>
6:<192.168.1.38>
7:<2024-07-22T11:21:30,065856+00:00>
<[8] [13611] [ ] [ ] [pts/3 ] [ ] [0.0.0.0 ] [2024-07-22T11:21:41,814051+00:00]>
0:<8>
1:<13611>
2:<>
3:<>
4:<pts/3>
5:<>
6:<0.0.0.0>
7:<2024-07-22T11:21:41,814051+00:00>
此代码任务的优点是该行可能是可写的,因此通过添加空字符将标记化字段保存在该行中。 这可以避免缓冲区溢出问题。