Extract multiple lines if match
I have a command that outputs information about all DIMM slots in blocks like the following:
ID SIZE TYPE
44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)
Manufacturer: NO DIMM
Serial Number: NO DIMM
Asset Tag: NO DIMM
Location Tag: P1-DIMMD1
Part Number: NO DIMM
Physical Memory Array: 43
Memory Error Data: Not Supported
Total Width: 0 bits
Data Width: 0 bits
Size: Not Populated
Form Factor: 9 (DIMM)
Set: None
Rank: Unknown
Memory Type: 2 (unknown)
Flags: 0x4
SMB_MDF_UNKNOWN (unknown)
Speed: Unknown
Configured Speed: Unknown
Device Locator: P1-DIMMD1
Bank Locator: P0_Node1_Channel0_Dimm0
Minimum Voltage: 1.20V
Maximum Voltage: 1.20V
Configured Voltage: 1.20V
The blocks start with the ID SIZE TYPE
header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.
I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag
field, but am unsure how to go about it. I am pretty sure this can be done with awk
but only know how to print the match awk '/P1-DIMMD1/'
or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'
Does anyone know how I could extract this whole block of data if the Location Tag
matches my search (P1-DIMMD1
)?
text-processing awk
add a comment |
I have a command that outputs information about all DIMM slots in blocks like the following:
ID SIZE TYPE
44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)
Manufacturer: NO DIMM
Serial Number: NO DIMM
Asset Tag: NO DIMM
Location Tag: P1-DIMMD1
Part Number: NO DIMM
Physical Memory Array: 43
Memory Error Data: Not Supported
Total Width: 0 bits
Data Width: 0 bits
Size: Not Populated
Form Factor: 9 (DIMM)
Set: None
Rank: Unknown
Memory Type: 2 (unknown)
Flags: 0x4
SMB_MDF_UNKNOWN (unknown)
Speed: Unknown
Configured Speed: Unknown
Device Locator: P1-DIMMD1
Bank Locator: P0_Node1_Channel0_Dimm0
Minimum Voltage: 1.20V
Maximum Voltage: 1.20V
Configured Voltage: 1.20V
The blocks start with the ID SIZE TYPE
header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.
I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag
field, but am unsure how to go about it. I am pretty sure this can be done with awk
but only know how to print the match awk '/P1-DIMMD1/'
or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'
Does anyone know how I could extract this whole block of data if the Location Tag
matches my search (P1-DIMMD1
)?
text-processing awk
add a comment |
I have a command that outputs information about all DIMM slots in blocks like the following:
ID SIZE TYPE
44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)
Manufacturer: NO DIMM
Serial Number: NO DIMM
Asset Tag: NO DIMM
Location Tag: P1-DIMMD1
Part Number: NO DIMM
Physical Memory Array: 43
Memory Error Data: Not Supported
Total Width: 0 bits
Data Width: 0 bits
Size: Not Populated
Form Factor: 9 (DIMM)
Set: None
Rank: Unknown
Memory Type: 2 (unknown)
Flags: 0x4
SMB_MDF_UNKNOWN (unknown)
Speed: Unknown
Configured Speed: Unknown
Device Locator: P1-DIMMD1
Bank Locator: P0_Node1_Channel0_Dimm0
Minimum Voltage: 1.20V
Maximum Voltage: 1.20V
Configured Voltage: 1.20V
The blocks start with the ID SIZE TYPE
header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.
I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag
field, but am unsure how to go about it. I am pretty sure this can be done with awk
but only know how to print the match awk '/P1-DIMMD1/'
or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'
Does anyone know how I could extract this whole block of data if the Location Tag
matches my search (P1-DIMMD1
)?
text-processing awk
I have a command that outputs information about all DIMM slots in blocks like the following:
ID SIZE TYPE
44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)
Manufacturer: NO DIMM
Serial Number: NO DIMM
Asset Tag: NO DIMM
Location Tag: P1-DIMMD1
Part Number: NO DIMM
Physical Memory Array: 43
Memory Error Data: Not Supported
Total Width: 0 bits
Data Width: 0 bits
Size: Not Populated
Form Factor: 9 (DIMM)
Set: None
Rank: Unknown
Memory Type: 2 (unknown)
Flags: 0x4
SMB_MDF_UNKNOWN (unknown)
Speed: Unknown
Configured Speed: Unknown
Device Locator: P1-DIMMD1
Bank Locator: P0_Node1_Channel0_Dimm0
Minimum Voltage: 1.20V
Maximum Voltage: 1.20V
Configured Voltage: 1.20V
The blocks start with the ID SIZE TYPE
header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.
I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag
field, but am unsure how to go about it. I am pretty sure this can be done with awk
but only know how to print the match awk '/P1-DIMMD1/'
or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'
Does anyone know how I could extract this whole block of data if the Location Tag
matches my search (P1-DIMMD1
)?
text-processing awk
text-processing awk
asked 1 hour ago
Jesse_bJesse_b
12.1k23064
12.1k23064
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
The following will match the tag given in the tag variable:
awk -v tag=P1-DIMMD1 '/ID SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'
The AWK script is
/ID SIZE TYPE/ {
block = $0
output = 0
next
}
{ block = block "n" $0 }
/Location Tag/ { output = ($0 ~ tag) }
/Configured Voltage/ && output { print block }
We accumulate a block in the block
variable, and output it when we reach the end of the block if we saw the right tag in the process.
add a comment |
You could use ed ... and sed, man!
You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d
The ed
command-string breaks down to four n
-separated commands:
- search forwards, using
/
, for the text "Location Tag: " followed by the value of the$wanted
variable - search backwards, using
?
, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE" - from that line (
.
), through (,
) the next line that matches "Configured Voltage", print those lines (p
) - quit ed:
q
Because ed auto-prints the matching line when you search, I used sed
here to delete those two lines.
add a comment |
Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.
#!/bin/sh
[ -z "$4" ] && file="-" || file="$4"
awk
-v BLOCKSTART_PATTERN="$1"
-v BLOCKEND_PATTERN="$2"
-v BLOCKMATCH_PATTERN="$3"
'
$0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
{ block = block "n" $0 }
$0 ~ BLOCKMATCH_PATTERN { output = 1 }
$0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
' "$file"
Usage: match_block START END MATCH [FILE]
.
If file is omitted, stdin
will be used.
In your case:
command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'
or
./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f495094%2fextract-multiple-lines-if-match%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The following will match the tag given in the tag variable:
awk -v tag=P1-DIMMD1 '/ID SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'
The AWK script is
/ID SIZE TYPE/ {
block = $0
output = 0
next
}
{ block = block "n" $0 }
/Location Tag/ { output = ($0 ~ tag) }
/Configured Voltage/ && output { print block }
We accumulate a block in the block
variable, and output it when we reach the end of the block if we saw the right tag in the process.
add a comment |
The following will match the tag given in the tag variable:
awk -v tag=P1-DIMMD1 '/ID SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'
The AWK script is
/ID SIZE TYPE/ {
block = $0
output = 0
next
}
{ block = block "n" $0 }
/Location Tag/ { output = ($0 ~ tag) }
/Configured Voltage/ && output { print block }
We accumulate a block in the block
variable, and output it when we reach the end of the block if we saw the right tag in the process.
add a comment |
The following will match the tag given in the tag variable:
awk -v tag=P1-DIMMD1 '/ID SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'
The AWK script is
/ID SIZE TYPE/ {
block = $0
output = 0
next
}
{ block = block "n" $0 }
/Location Tag/ { output = ($0 ~ tag) }
/Configured Voltage/ && output { print block }
We accumulate a block in the block
variable, and output it when we reach the end of the block if we saw the right tag in the process.
The following will match the tag given in the tag variable:
awk -v tag=P1-DIMMD1 '/ID SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'
The AWK script is
/ID SIZE TYPE/ {
block = $0
output = 0
next
}
{ block = block "n" $0 }
/Location Tag/ { output = ($0 ~ tag) }
/Configured Voltage/ && output { print block }
We accumulate a block in the block
variable, and output it when we reach the end of the block if we saw the right tag in the process.
edited 49 mins ago
answered 54 mins ago
Stephen KittStephen Kitt
167k24375453
167k24375453
add a comment |
add a comment |
You could use ed ... and sed, man!
You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d
The ed
command-string breaks down to four n
-separated commands:
- search forwards, using
/
, for the text "Location Tag: " followed by the value of the$wanted
variable - search backwards, using
?
, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE" - from that line (
.
), through (,
) the next line that matches "Configured Voltage", print those lines (p
) - quit ed:
q
Because ed auto-prints the matching line when you search, I used sed
here to delete those two lines.
add a comment |
You could use ed ... and sed, man!
You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d
The ed
command-string breaks down to four n
-separated commands:
- search forwards, using
/
, for the text "Location Tag: " followed by the value of the$wanted
variable - search backwards, using
?
, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE" - from that line (
.
), through (,
) the next line that matches "Configured Voltage", print those lines (p
) - quit ed:
q
Because ed auto-prints the matching line when you search, I used sed
here to delete those two lines.
add a comment |
You could use ed ... and sed, man!
You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d
The ed
command-string breaks down to four n
-separated commands:
- search forwards, using
/
, for the text "Location Tag: " followed by the value of the$wanted
variable - search backwards, using
?
, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE" - from that line (
.
), through (,
) the next line that matches "Configured Voltage", print those lines (p
) - quit ed:
q
Because ed auto-prints the matching line when you search, I used sed
here to delete those two lines.
You could use ed ... and sed, man!
You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d
The ed
command-string breaks down to four n
-separated commands:
- search forwards, using
/
, for the text "Location Tag: " followed by the value of the$wanted
variable - search backwards, using
?
, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE" - from that line (
.
), through (,
) the next line that matches "Configured Voltage", print those lines (p
) - quit ed:
q
Because ed auto-prints the matching line when you search, I used sed
here to delete those two lines.
answered 23 mins ago
Jeff SchallerJeff Schaller
39.4k1054126
39.4k1054126
add a comment |
add a comment |
Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.
#!/bin/sh
[ -z "$4" ] && file="-" || file="$4"
awk
-v BLOCKSTART_PATTERN="$1"
-v BLOCKEND_PATTERN="$2"
-v BLOCKMATCH_PATTERN="$3"
'
$0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
{ block = block "n" $0 }
$0 ~ BLOCKMATCH_PATTERN { output = 1 }
$0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
' "$file"
Usage: match_block START END MATCH [FILE]
.
If file is omitted, stdin
will be used.
In your case:
command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'
or
./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
add a comment |
Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.
#!/bin/sh
[ -z "$4" ] && file="-" || file="$4"
awk
-v BLOCKSTART_PATTERN="$1"
-v BLOCKEND_PATTERN="$2"
-v BLOCKMATCH_PATTERN="$3"
'
$0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
{ block = block "n" $0 }
$0 ~ BLOCKMATCH_PATTERN { output = 1 }
$0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
' "$file"
Usage: match_block START END MATCH [FILE]
.
If file is omitted, stdin
will be used.
In your case:
command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'
or
./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
add a comment |
Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.
#!/bin/sh
[ -z "$4" ] && file="-" || file="$4"
awk
-v BLOCKSTART_PATTERN="$1"
-v BLOCKEND_PATTERN="$2"
-v BLOCKMATCH_PATTERN="$3"
'
$0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
{ block = block "n" $0 }
$0 ~ BLOCKMATCH_PATTERN { output = 1 }
$0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
' "$file"
Usage: match_block START END MATCH [FILE]
.
If file is omitted, stdin
will be used.
In your case:
command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'
or
./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file
Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.
#!/bin/sh
[ -z "$4" ] && file="-" || file="$4"
awk
-v BLOCKSTART_PATTERN="$1"
-v BLOCKEND_PATTERN="$2"
-v BLOCKMATCH_PATTERN="$3"
'
$0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
{ block = block "n" $0 }
$0 ~ BLOCKMATCH_PATTERN { output = 1 }
$0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
' "$file"
Usage: match_block START END MATCH [FILE]
.
If file is omitted, stdin
will be used.
In your case:
command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'
or
./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file
answered 27 mins ago
RoVoRoVo
2,753216
2,753216
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
add a comment |
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
You could even write this directly as an AWK script, instead of a shell script which calls AWK.
– Stephen Kitt
19 mins ago
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f495094%2fextract-multiple-lines-if-match%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown