如何使用 QRegExp 解析 pacmd 列表输出并查找接收器索引和名称?
How to parse pacmd list output and find sink indexes and names using QRegExp?
通常从终端我使用命令:
pacmd list-sinks|awk '/index:/ {print [=10=]} /name:/ {print [=10=]};'
这给了我这样的输出:
index: 0
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
index: 1
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
* index: 2
name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>
但显然从 Qt
开始,当使用 QProcess
命令时,使用 awk
进行解析不起作用,它根本不进行任何解析并生成整个输出您期望指挥 pacmd list-sinks
。整个输出如下:
Welcome to PulseAudio! Use "help" for usage information.
>>> 3 sink(s) available.
index: 0
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9050
volume: 0: 45% 1: 45%
0: -20,78 dB 1: -20,78 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 0,00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 0
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
Stereo
used by: 0
linked by: 0
configured latency: 0,00 ms; range is 0,50 .. 371,52 ms
card: 0 <alsa_card.pci-0000_01_00.1>
module: 5
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "HDMI 0"
alsa.id = "HDMI 0"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "3"
alsa.card = "1"
alsa.card_name = "HDA NVidia"
alsa.long_card_name = "HDA NVidia at 0xf7080000 irq 17"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:01:00.1"
sysfs.path = "/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1"
device.bus = "pci"
device.vendor.id = "10de"
device.vendor.name = "NVIDIA Corporation"
device.product.id = "0e1b"
device.product.name = "GK107 HDMI Audio Controller"
device.string = "hdmi:1"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "hdmi-stereo"
device.profile.description = "Digital Stereo (HDMI)"
device.description = "GK107 HDMI Audio Controller Digital Stereo (HDMI)"
alsa.mixer_name = "Nvidia GPU 42 HDMI/DP"
alsa.components = "HDA:10de0042,104383f3,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
hdmi-output-0: HDMI / DisplayPort (priority 5900, latency offset 0 usec, available: no)
properties:
device.icon_name = "video-display"
active port: <hdmi-output-0>
index: 1
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9959
volume: 0: 27% 1: 27%
0: -34,20 dB 1: -34,20 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 0,00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 1
sample spec: s16le 2ch 48000Hz
channel map: front-left,front-right
Stereo
used by: 0
linked by: 0
configured latency: 0,00 ms; range is 0,50 .. 341,33 ms
card: 1 <alsa_card.pci-0000_00_1b.0>
module: 6
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "ALC269VB Analog"
alsa.id = "ALC269VB Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xf7330000 irq 38"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1b.0"
sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "1e20"
device.product.name = "7 Series/C210 Series Chipset Family High Definition Audio Controller"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Built-in Audio Analog Stereo"
alsa.mixer_name = "Realtek ALC269VB"
alsa.components = "HDA:10ec0269,1028052c,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
analog-output: Analog Output (priority 9900, latency offset 0 usec, available: unknown)
properties:
analog-output-speaker: Speakers (priority 10000, latency offset 0 usec, available: no)
properties:
device.icon_name = "audio-speakers"
analog-output-headphones: Headphones (priority 9000, latency offset 0 usec, available: yes)
properties:
device.icon_name = "audio-headphones"
active port: <analog-output-headphones>
* index: 2
name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: RUNNING
suspend cause:
priority: 9048
volume: 0: 45% 1: 45%
0: -20,78 dB 1: -20,78 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 31,29 ms
max request: 4 KiB
max rewind: 344 KiB
monitor source: 4
sample spec: s16le 2ch 48000Hz
channel map: front-left,front-right
Stereo
used by: 1
linked by: 1
configured latency: 26,00 ms; range is 26,00 .. 1837,50 ms
card: 3 <alsa_card.usb-0d8c_C-Media_USB_Audio_Device-00-Device>
module: 22
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "USB Audio"
alsa.id = "USB Audio"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "2"
alsa.card_name = "C-Media USB Audio Device"
alsa.long_card_name = "C-Media USB Audio Device at usb-0000:00:14.0-1, full speed"
alsa.driver_name = "snd_usb_audio"
device.bus_path = "pci-0000:00:14.0-usb-0:1:1.0"
sysfs.path = "/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/sound/card2"
udev.id = "usb-0d8c_C-Media_USB_Audio_Device-00-Device"
device.bus = "usb"
device.vendor.id = "0d8c"
device.vendor.name = "C-Media Electronics, Inc."
device.product.id = "000c"
device.product.name = "Audio Adapter"
device.serial = "0d8c_C-Media_USB_Audio_Device"
device.string = "iec958:2"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "176400"
device.access_mode = "mmap+timer"
device.profile.name = "iec958-stereo"
device.profile.description = "Digital Stereo (IEC958)"
device.description = "Audio Adapter Digital Stereo (IEC958)"
alsa.mixer_name = "USB Mixer"
alsa.components = "USB0d8c:000c"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-usb"
ports:
iec958-stereo-output: Digital Output (S/PDIF) (priority 0, latency offset 0 usec, available: unknown)
properties:
active port: <iec958-stereo-output>
>>>
我想我指挥错了。我使用 awk
命令和解析的代码如下:
QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks"<<"|awk '/index:/ {print [=13=]} /name:/ {print [=13=]};'";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
p.waitForFinished();
reply = p.readAllStandardOutput();
qDebug()<<reply<<endl;
}
else
{
qDebug()<< "Error using pacmd for getting list of sinks";
}
所以,现在,我试图在不使用 awk
的情况下解析索引和名称。我能够找到索引,但找不到名称。代码如下:
QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
p.waitForFinished();
reply = p.readAllStandardOutput();
QRegExp rx("index: \d+|'", Qt::CaseInsensitive);
QStringList indexList;
int pos = 0;
while ((pos = rx.indexIn(reply, pos)) != -1) {
indexList << rx.capturedTexts();
pos += rx.matchedLength();
}
foreach (QString index, indexList) {
qDebug()<<index;
}
QRegExp rx1("name: \s*|'", Qt::CaseInsensitive);
QStringList nameList;
pos = 0;
while ((pos = rx1.indexIn(reply, pos)) != -1) {
nameList << rx1.capturedTexts();
pos += rx1.matchedLength();
}
foreach (QString index, nameList) {
qDebug()<<index;
}
}
else
{
qDebug()<< "Error using pacmd for getting list of sinks";
}
我从代码中得到的输出如下:
"index: 0"
"index: 1"
"index: 2"
"name: "
"name: "
"name: "
我怎样才能得到像下面的字符串这样的名字?
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
难道 "name: \s*|'"
也不是捕获名称的正则表达式的正确模式吗?
谢谢。
首先说明您第一次尝试 运行ning awk 失败的原因:
管道'|'是 shell 的一个特征(例如 bash)。当您 运行 使用 QProcess 的可执行文件时,这不是 运行 shell 中的可执行文件,它直接 运行 是可执行文件。因此,在您的代码中,pacmd
可执行文件是 运行,命令行参数为 list-sinks
和 |awk '/index:/ {print [=12=]} /name:/ {print [=12=]};'
.
要使其工作,您需要首先 运行 list-sinks
,获取其输出,然后 运行 awk
并将其作为输入传递,或者如果您不介意依赖特定的 shell,您还可以 运行 shell 并将命令行传递给它(在 bash 的情况下,您将传递-c
和 pacmd list-sinks|awk '/index:/ {print [=16=]} /name:/ {print [=16=]};'
作为 /bin/bash
).
的参数
关于使用正则表达式解析 name: something
,表达式 \s
匹配 whitespace。因此,只需将 name: \s*
更改为 name: \S*
(大写 S
)以获得非空白字符。
通常从终端我使用命令:
pacmd list-sinks|awk '/index:/ {print [=10=]} /name:/ {print [=10=]};'
这给了我这样的输出:
index: 0
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
index: 1
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
* index: 2
name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>
但显然从 Qt
开始,当使用 QProcess
命令时,使用 awk
进行解析不起作用,它根本不进行任何解析并生成整个输出您期望指挥 pacmd list-sinks
。整个输出如下:
Welcome to PulseAudio! Use "help" for usage information.
>>> 3 sink(s) available.
index: 0
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9050
volume: 0: 45% 1: 45%
0: -20,78 dB 1: -20,78 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 0,00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 0
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
Stereo
used by: 0
linked by: 0
configured latency: 0,00 ms; range is 0,50 .. 371,52 ms
card: 0 <alsa_card.pci-0000_01_00.1>
module: 5
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "HDMI 0"
alsa.id = "HDMI 0"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "3"
alsa.card = "1"
alsa.card_name = "HDA NVidia"
alsa.long_card_name = "HDA NVidia at 0xf7080000 irq 17"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:01:00.1"
sysfs.path = "/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1"
device.bus = "pci"
device.vendor.id = "10de"
device.vendor.name = "NVIDIA Corporation"
device.product.id = "0e1b"
device.product.name = "GK107 HDMI Audio Controller"
device.string = "hdmi:1"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "hdmi-stereo"
device.profile.description = "Digital Stereo (HDMI)"
device.description = "GK107 HDMI Audio Controller Digital Stereo (HDMI)"
alsa.mixer_name = "Nvidia GPU 42 HDMI/DP"
alsa.components = "HDA:10de0042,104383f3,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
hdmi-output-0: HDMI / DisplayPort (priority 5900, latency offset 0 usec, available: no)
properties:
device.icon_name = "video-display"
active port: <hdmi-output-0>
index: 1
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9959
volume: 0: 27% 1: 27%
0: -34,20 dB 1: -34,20 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 0,00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 1
sample spec: s16le 2ch 48000Hz
channel map: front-left,front-right
Stereo
used by: 0
linked by: 0
configured latency: 0,00 ms; range is 0,50 .. 341,33 ms
card: 1 <alsa_card.pci-0000_00_1b.0>
module: 6
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "ALC269VB Analog"
alsa.id = "ALC269VB Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xf7330000 irq 38"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1b.0"
sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "1e20"
device.product.name = "7 Series/C210 Series Chipset Family High Definition Audio Controller"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "65536"
device.buffering.fragment_size = "32768"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Built-in Audio Analog Stereo"
alsa.mixer_name = "Realtek ALC269VB"
alsa.components = "HDA:10ec0269,1028052c,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
analog-output: Analog Output (priority 9900, latency offset 0 usec, available: unknown)
properties:
analog-output-speaker: Speakers (priority 10000, latency offset 0 usec, available: no)
properties:
device.icon_name = "audio-speakers"
analog-output-headphones: Headphones (priority 9000, latency offset 0 usec, available: yes)
properties:
device.icon_name = "audio-headphones"
active port: <analog-output-headphones>
* index: 2
name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
state: RUNNING
suspend cause:
priority: 9048
volume: 0: 45% 1: 45%
0: -20,78 dB 1: -20,78 dB
balance 0,00
base volume: 100%
0,00 dB
volume steps: 65537
muted: no
current latency: 31,29 ms
max request: 4 KiB
max rewind: 344 KiB
monitor source: 4
sample spec: s16le 2ch 48000Hz
channel map: front-left,front-right
Stereo
used by: 1
linked by: 1
configured latency: 26,00 ms; range is 26,00 .. 1837,50 ms
card: 3 <alsa_card.usb-0d8c_C-Media_USB_Audio_Device-00-Device>
module: 22
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "USB Audio"
alsa.id = "USB Audio"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "2"
alsa.card_name = "C-Media USB Audio Device"
alsa.long_card_name = "C-Media USB Audio Device at usb-0000:00:14.0-1, full speed"
alsa.driver_name = "snd_usb_audio"
device.bus_path = "pci-0000:00:14.0-usb-0:1:1.0"
sysfs.path = "/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/sound/card2"
udev.id = "usb-0d8c_C-Media_USB_Audio_Device-00-Device"
device.bus = "usb"
device.vendor.id = "0d8c"
device.vendor.name = "C-Media Electronics, Inc."
device.product.id = "000c"
device.product.name = "Audio Adapter"
device.serial = "0d8c_C-Media_USB_Audio_Device"
device.string = "iec958:2"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "176400"
device.access_mode = "mmap+timer"
device.profile.name = "iec958-stereo"
device.profile.description = "Digital Stereo (IEC958)"
device.description = "Audio Adapter Digital Stereo (IEC958)"
alsa.mixer_name = "USB Mixer"
alsa.components = "USB0d8c:000c"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-usb"
ports:
iec958-stereo-output: Digital Output (S/PDIF) (priority 0, latency offset 0 usec, available: unknown)
properties:
active port: <iec958-stereo-output>
>>>
我想我指挥错了。我使用 awk
命令和解析的代码如下:
QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks"<<"|awk '/index:/ {print [=13=]} /name:/ {print [=13=]};'";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
p.waitForFinished();
reply = p.readAllStandardOutput();
qDebug()<<reply<<endl;
}
else
{
qDebug()<< "Error using pacmd for getting list of sinks";
}
所以,现在,我试图在不使用 awk
的情况下解析索引和名称。我能够找到索引,但找不到名称。代码如下:
QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
p.waitForFinished();
reply = p.readAllStandardOutput();
QRegExp rx("index: \d+|'", Qt::CaseInsensitive);
QStringList indexList;
int pos = 0;
while ((pos = rx.indexIn(reply, pos)) != -1) {
indexList << rx.capturedTexts();
pos += rx.matchedLength();
}
foreach (QString index, indexList) {
qDebug()<<index;
}
QRegExp rx1("name: \s*|'", Qt::CaseInsensitive);
QStringList nameList;
pos = 0;
while ((pos = rx1.indexIn(reply, pos)) != -1) {
nameList << rx1.capturedTexts();
pos += rx1.matchedLength();
}
foreach (QString index, nameList) {
qDebug()<<index;
}
}
else
{
qDebug()<< "Error using pacmd for getting list of sinks";
}
我从代码中得到的输出如下:
"index: 0"
"index: 1"
"index: 2"
"name: "
"name: "
"name: "
我怎样才能得到像下面的字符串这样的名字?
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
难道 "name: \s*|'"
也不是捕获名称的正则表达式的正确模式吗?
谢谢。
首先说明您第一次尝试 运行ning awk 失败的原因:
管道'|'是 shell 的一个特征(例如 bash)。当您 运行 使用 QProcess 的可执行文件时,这不是 运行 shell 中的可执行文件,它直接 运行 是可执行文件。因此,在您的代码中,pacmd
可执行文件是 运行,命令行参数为 list-sinks
和 |awk '/index:/ {print [=12=]} /name:/ {print [=12=]};'
.
要使其工作,您需要首先 运行 list-sinks
,获取其输出,然后 运行 awk
并将其作为输入传递,或者如果您不介意依赖特定的 shell,您还可以 运行 shell 并将命令行传递给它(在 bash 的情况下,您将传递-c
和 pacmd list-sinks|awk '/index:/ {print [=16=]} /name:/ {print [=16=]};'
作为 /bin/bash
).
关于使用正则表达式解析 name: something
,表达式 \s
匹配 whitespace。因此,只需将 name: \s*
更改为 name: \S*
(大写 S
)以获得非空白字符。