在Linux平台使用 ss 命令 -p 选项:
-p, --processes
Show process using socket.
比如:
Process
users:(("node",pid=13051,fd=22))
users:(("sshd",pid=11700,fd=4),("sshd",pid=11659,fd=4))
显示使用该socket的进程的信息如上述格式所示,一个socket可以有多个进程使用。接下来我们根据上述字符串用正则表达式来提取出一个socket多个进程时,其进程的信息。
正则表达式是一种用于描述文本模式的语言,常用于字符串匹配、搜索和替换等操作。
C++11 中引入了一个新的标准库,即
std::regex 对象的构造函数接受一个字符串参数,表示正则表达式模式。正则表达式模式是一种特殊的字符串,用于描述文本模式。正则表达式模式中包含了一些特殊字符和语法,用于指定匹配规则和匹配范围。例如,在正则表达式模式中,^ 表示文本的开头,$ 表示文本的结尾,. 表示任意字符,* 表示匹配零个或多个字符,+ 表示匹配一个或多个字符,[] 表示匹配一组字符中的任意一个,() 表示将匹配结果保存到一个子匹配组中等等。
匹配操作通常使用 std::regex_match、std::regex_search、std::regex_replace 等函数来实现。这些函数接受一个字符串参数和一个正则表达式对象,用于对字符串进行匹配、搜索和替换等操作。其中,std::regex_match 函数用于对整个字符串进行匹配,std::regex_search 函数用于在字符串中搜索匹配项,std::regex_replace 函数用于替换字符串中的匹配项。
正则表达式是一个用于描述字符串模式的语言,可以用于匹配、查找、替换字符串中的文本。在正则表达式中,有一些特殊的字符和规则,需要特别注意。
下面是一些常见的正则表达式中的字符和规则:
.:匹配任何一个字符,除了换行符 \n。
*:匹配前面的字符或字符类零个或多个。
+:匹配前面的字符或字符类一个或多个。
?:匹配前面的字符或字符类零个或一个。
[]:匹配括号中的任何一个字符。例如,[abc] 匹配字符 a、b 或 c。
[^]:匹配除了括号中的任何一个字符之外的任何一个字符。例如,[^abc] 匹配除了字符 a、b 和 c 之外的任何一个字符。
|:表示或。例如,a|b 匹配字符 a 或 b。
():用于分组,可以将多个字符或字符类组合在一起。例如,(ab)+ 匹配一个或多个连续的 ab。
^:表示行首,用于匹配字符串的开头。例如,^abc 匹配以 abc 开头的字符串。
$:表示行尾,用于匹配字符串的结尾。例如,abc$ 匹配以 abc 结尾的字符串。
\d:匹配任何一个数字字符,等价于 [0-9]。
\w:匹配任何一个单词字符,包括字母、数字和下划线,等价于 [a-zA-Z0-9_]。
\s:匹配任何一个空白字符,包括空格、制表符和换行符。
\b:匹配单词边界,即单词和非单词字符之间的位置。
需要注意的是,在正则表达式中,一些字符和符号具有特殊的含义,例如 .、*、+、? 等等,如果需要匹配这些字符本身,需要使用转义符号 \ 来将其转义,例如 \\.、\\*、\\+、\\? 等等。
除了前面提到的字符和规则之外,正则表达式还有一些高级的用法,可以用于更复杂的文本处理。下面是一些常见的高级用法:
{n,m}:匹配前面的字符或字符类至少 n 次,最多 m 次。例如,a{2,3} 匹配两个或三个连续的字符 a。
{n,}:匹配前面的字符或字符类至少 n 次。例如,a{3,} 匹配三个或更多连续的字符 a。
{,m}:匹配前面的字符或字符类最多 m 次。例如,a{,3} 匹配零个、一个、两个或三个连续的字符 a。
():用于捕获分组,可以将匹配的结果存储到一个变量中。例如,([a-z]+) 匹配一个或多个小写字母,并将结果存储到一个变量中。
(?:):用于非捕获分组,可以将多个字符或字符类组合在一起,但不会将结果存储到一个变量中。例如,(?:ab)+ 匹配一个或多个连续的 ab,但不会将结果存储到一个变量中。
(?=):用于正向先行断言,表示前面的字符或字符类必须匹配成功,但不会将其包含在匹配结果中。例如,\\d+(?=元) 匹配一个或多个数字字符,但只有在其后面紧跟着一个 元 字符时才匹配成功。
(?!):用于负向先行断言,表示前面的字符或字符类必须匹配失败,但不会将其包含在匹配结果中。例如,\\d+(?!元) 匹配一个或多个数字字符,但只有在其后面不紧跟着一个 元 字符时才匹配成功。
在
std::regex pattern("\\d+"); // 匹配一个或多个数字
可以使用 std::regex_match、std::regex_search、std::regex_replace 等函数对字符串进行正则表达式匹配、搜索和替换等操作。
std::regex_match 函数用于对整个字符串进行匹配,如果匹配成功则返回 true,否则返回 false。例如:
std::string s = "123";
std::regex pattern("\\d+");
if (std::regex_match(s, pattern)) {
std::cout << "Match!" << std::endl;
} else {
std::cout << "No match." << std::endl;
}
std::regex_search 函数用于在字符串中搜索匹配项,并返回第一个匹配结果。如果找到匹配项,则返回 true,否则返回 false。例如:
std::string s = "123abc";
std::regex pattern("\\d+");
std::smatch match;
if (std::regex_search(s, match, pattern)) {
std::cout << "Match found: " << match.str() << std::endl;
} else {
std::cout << "No match found." << std::endl;
}
std::regex_replace 函数用于替换字符串中的匹配项。例如:
std::string s = "123abc";
std::regex pattern("\\d+");
std::string replacement = "456";
std::string result = std::regex_replace(s, pattern, replacement);
std::cout << "Original string: " << s << std::endl; // "123abc"
std::cout << "Replaced string: " << result << std::endl; // "456abc"
#include
#include
#include
void fun1()
{
std::string s = "123";
std::regex pattern("\\d+");
if (std::regex_match(s, pattern)) {
std::cout << "Match!" << std::endl;
} else {
std::cout << "No match." << std::endl;
}
}
void fun2()
{
std::string s = "123abc789";
std::regex pattern("\\d+");
std::smatch match;
if (std::regex_search(s, match, pattern)) {
std::cout << "Match fisrt string found: " << match.str() << std::endl;
} else {
std::cout << "No match found." << std::endl;
}
}
void fun3()
{
std::string s = "123abc789";
std::regex pattern("\\d+");
std::string replacement = "456";
std::string result = std::regex_replace(s, pattern, replacement);
std::cout << "Original string: " << s << std::endl; // "123abc"
std::cout << "Replaced string: " << result << std::endl; // "456abc"
}
int main() {
fun1();
fun2();
fun3();
}
$ ./a.out
Match!
Match fisrt string found: 123
Original string: 123abc789
Replaced string: 456abc456
std::regex pattern(“\d+”); 是一个 C++11 中的正则表达式模式,用于匹配字符串中的数字。
在正则表达式语法中,反斜线 \ 是一个转义字符,用于表示后面的字符具有特殊的意义。\d 表示数字字符。+ 是一个量词,表示匹配前面的模式一次或多次。
因此,\d+ 表示匹配一个或多个数字。
除了 std::regex 类之外,C++11 的正则表达式库还引入了一些新的类型和函数,用于更方便地进行正则表达式匹配、搜索和替换等操作。
(1)std::smatch 类型
std::smatch 类型表示一个正则表达式匹配结果的集合。当使用 std::regex_search 或 std::regex_match 函数匹配成功时,这些函数会将匹配结果保存在一个 std::smatch 类型的对象中。std::smatch 对象可以通过下标操作符或迭代器来访问匹配结果。
std::string s = "Hello, world!";
std::regex pattern("\\w+");
std::smatch match;
if (std::regex_search(s, match, pattern)) {
std::cout << "Match found: " << match.str() << std::endl; // "Hello"
}
上面的代码中,std::regex_search 函数用正则表达式模式 \w+ 在字符串中查找第一个单词,并将匹配结果保存在 std::smatch 类型的对象中。然后使用 match.str() 成员函数来访问匹配结果。
访问匹配结果有两种方式,一种是match.str() 成员函数,一种是match[]。如下所示:
#include
#include
#include
int main() {
std::string s = "[email protected]";
std::regex pattern("([^@]+)@([^@]+)");
std::smatch match;
if (std::regex_search(s, match, pattern)) {
std::cout << "s: " << match[0] << std::endl;
std::cout << "用户名: " << match[1] << std::endl; // "example_user"
std::cout << "域名: " << match[2] << std::endl; // "example.com"
std::cout << "s: " << match.str() << std::endl;
std::cout << "用户名: " << match.str(1) << std::endl; // "example_user"
std::cout << "域名: " << match.str(2) << std::endl; // "example.com"
}
return 0;
}
s: example_user@example.com
用户名: example_user
域名: example.com
s: example_user@example.com
用户名: example_user
域名: example.com
(2)std::sregex_iterator 类型
std::sregex_iterator 类型表示一个正则表达式匹配结果的迭代器。当使用 std::sregex_iterator 类型的迭代器遍历匹配结果时,每次迭代返回一个 std::smatch 类型的对象,表示一个匹配项。
例如:
std::string s = "Hello, world!";
std::regex pattern("\\w+");
std::sregex_iterator it(s.begin(), s.end(), pattern);
std::sregex_iterator end;
while (it != end) {
std::smatch match = *it;
std::cout << "Match found: " << match.str() << std::endl;
++it;
}
上面的代码中,std::sregex_iterator 类型的迭代器 it 用于遍历字符串中的所有单词,并将每个匹配结果保存在 std::smatch 类型的对象中。然后使用 match.str() 成员函数来访问匹配结果。
(3)std::regex_replace 函数的格式化替换功能
C++11 引入了一个新的格式化替换语法,可以在 std::regex_replace 函数中使用。这个语法使用 $N 来表示第 N 个子匹配组中的匹配结果,其中 N 是一个从 0 开始的整数。
例如:
std::string s = "John Smith";
std::regex pattern("(\\w+) (\\w+)");
std::string replacement = "$2, $1";
std::string result = std::regex_replace(s, pattern, replacement);
std::cout << "Original string: " << s << std::endl; // "John Smith"
std::cout << "Replaced string: " << result << std::endl; // "Smith, John"
上面的代码中,std::regex_replace 函数使用正则表达式 (\w+) (\w+) 匹配字符串中的两个单词,并将它们的顺序颠倒,然后使用 $2, $1 格式的语法将它们替换为新的字符串。
#include
#include
#include
void fun1()
{
std::string s = "Hello, world!";
std::regex pattern("\\w+");
std::smatch match;
if (std::regex_search(s, match, pattern)) {
std::cout << "Match found: " << match.str() << std::endl; // "Hello"
}
}
void fun2()
{
std::string s = "Hello, world!";
std::regex pattern("\\w+");
std::sregex_iterator it(s.begin(), s.end(), pattern);
std::sregex_iterator end;
while (it != end) {
std::smatch match = *it;
std::cout << "Match found: " << match.str() << std::endl;
++it;
}
}
void fun3()
{
std::string s = "John Smith";
std::regex pattern("(\\w+) (\\w+)");
std::string replacement = "$2, $1";
std::string result = std::regex_replace(s, pattern, replacement);
std::cout << "Original string: " << s << std::endl; // "John Smith"
std::cout << "Replaced string: " << result << std::endl; // "Smith, John"
}
int main() {
fun1();
fun2();
fun3();
}
$ ./a.out
Match found: Hello
Match found: Hello
Match found: world
Original string: John Smith
Replaced string: Smith, John
这个正则表达式 \\w+ 匹配一个或多个连续的单词字符。其中:
\\w 表示匹配任何一个单词字符,包括字母、数字和下划线。这个字符类等价于 [ a-z A-Z 0-9 _ ]。
+表示匹配一个或多个前面的字符或字符类。
#include
#include
#include
#include
struct ProcessInfo {
std::string program_name;
int pid;
int fd;
ProcessInfo(std::string name, int p, int f):
program_name(name), pid(p), fd(f) {}
};
int main() {
std::string process_info = R"((("task1",pid=11700,fd=4),("task2",pid=11659,fd=4),("task3",pid=12000,fd=4)))";
//使用了一个正则表达式模式(pattern)来匹配进程信息字符串中的每个进程
//R"(...)" 表示一个原始字符串字面量,其中 ... 是一个字符串,可以包含任何字符,包括换行符和引号等特殊字符。
//每个进程信息都是以 ("program_name",pid=pid_value,fd=fd_value) 的形式出现,
//并且多个进程信息之间用逗号 , 分割
std::regex pattern(R"(\((\"[^\"]+\"),pid=(\d+),fd=(\d+)\))");
//使用 std::sregex_iterator 类型的迭代器(it)遍历所有匹配项
std::sregex_iterator it(process_info.begin(), process_info.end(), pattern);
std::sregex_iterator end;
std::vector<ProcessInfo> processes;
while (it != end) {
std::smatch match = *it;
std::string program_name = match[1];
int pid = std::stoi(match[2]);
int fd = std::stoi(match[3]);
processes.emplace_back(ProcessInfo(program_name, pid, fd));
++it;
}
for (auto& proc : processes) {
std::cout << "Program name: " << proc.program_name
<< ", PID: " << proc.pid
<< ", FD: " << proc.fd
<< std::endl;
}
return 0;
}
# ./a.out
Program name: "task1", PID: 11700, FD: 4
Program name: "task2", PID: 11659, FD: 4
Program name: "task3", PID: 12000, FD: 4
在上面的示例代码中,使用了 std::regex 对象来构建正则表达式模式,然后通过 std::sregex_iterator 类型的迭代器遍历所有匹配项,并使用 std::smatch 类型的对象来保存匹配结果。这些类型都是 C++11 中新引入的,用于对正则表达式进行更方便的匹配、搜索和替换等操作。
其中std::regex pattern:
std::regex pattern(R"(\((\"[^\"]+\"),pid=(\d+),fd=(\d+)\))");
std::regex 是 C++11 中的正则表达式库,用于构建正则表达式对象。pattern 是一个 std::regex 对象,通过调用 std::regex 构造函数来初始化。
正则表达式模式字符串包含以下几个部分:
(1)R"()" 是原始字符串字面量,表示其中的字符不需要进行转义处理。
(2)( 和 ) 分别表示匹配左括号 ( 和右括号 )。
(3)“[^”]+" 表示匹配双引号 " 中的任意字符,不包括双引号本身。
(\"[^\"]+\"),pid=(\d+),fd=(\d+)
" 表示匹配双引号 “,其中 \ 是转义字符,表示后面的字符是特殊字符。
[^”]+ 表示匹配一个或多个非双引号字符。
(4),pid= 表示匹配逗号 , 后面的字符串 pid=。
(5)(\d+) 表示匹配一个或多个数字。
(6),fd= 表示匹配逗号 , 后面的字符串 fd=。
(7)(\d+) 表示匹配一个或多个数字。
备注: “[^”]+" 表示匹配双引号 " 中的任意字符,不包括双引号本身。这样可以避免匹配到多个进程信息的情况。
因此,这个正则表达式模式可以匹配形如 (“program_name”,pid=pid_value,fd=fd_value) 的字符串,其中 program_name 是由双引号包围的任意字符,pid_value 和 fd_value 是任意数字。