I am using system(3) on Linux in c++ programs. Now I need to store the output of system(3) in an array or sequence. How I can store the output of system(3).
I am using following:
system("grep -A1 \"<weakObject>\" file_name | grep \"name\" |
grep -Po \"xoc.[^<]*\" | cut -d \".\" -f5 ");
which gives output:
changin
fdjgjkds
dglfvk
dxkfjl
I need to store this output to an array of strings or Sequence of string.
Thanks in advance
system spawns a new shell process that isn't connected to the parent through a pipe or something else.
You need to use the popen library function instead. Then read the output and push each string into your array as you encounter newline characters.
FILE *fp = popen("grep -A1 \"<weakObject>\" file_name | grep \"name\" |
grep -Po \"xoc.[^<]*\" | cut -d \".\" -f5 ", "r");
char buf[1024];
while (fgets(buf, 1024, fp)) {
/* do something with buf */
}
fclose(fp);
You should use popen to read the command output from stdin. so, you'd do something like:
FILE *pPipe;
pPipe = popen("grep -A1 \"\" file_name | grep \"name\" | grep -Po \"xoc.[^<]*\" | cut -d \".\" -f5 ", "rt")
to open it in read text mode and then use fgets or something similar to read from the pipe:
fgets(psBuffer, 128, pPipe)
The esier way:
std::stringstream result_stream;
std::streambuf *backup = std::cout.rdbuf( result_stream.rdbuf() );
int res = system("grep -A1 \"<weakObject>\" file_name | grep \"name\" |
grep -Po \"xoc.[^<]*\" | cut -d \".\" -f5 ");
std::cout.rdbuf(backup);
std::cout << result_stream.str();
Related
I'm trying to use the boost::pool memory pool from #include "boost/pool/pool.hpp".
I want to check how much memory is allocated with boost::pool so I run the command system("ps aux | grep myProgramExe | grep -v grep | awk '{print $5}'"); which gives me the (from the ps man page) VSZ - virtual memory size of the process in KiB (1024-byte units). Device mappings are currently excluded; this is subject to change. (alias vsize).
I'm getting something strange:
Code (code is indented 4 spaces, plus another 4 because it's embedded in a list)
int main()
{
{
boost::pool<> pool(4, 1);
system("ps aux | grep boostHash | grep -v grep | awk '{print \"1. \" $5}'");
void *a = pool.malloc();
pool.free(a);
system("ps aux | grep boostHash | grep -v grep | awk '{print \"2. \" $5}'");
}
system("ps aux | grep boostHash | grep -v grep | awk '{print \"3. \" $5}'");
}
The output is:
1. 18908
2. 19040
3. 19040
Which is strange, because:
a. I wanted to allocate only 4 bytes (the next allocation should be only 1 instance).
b. The memory isn't being free'd when the block is over and pool is dead.
Now I want to allocate instance of size 128, and I want to allocate 1024 like this in the next allocation:
int main()
{
{
boost::pool<> pool(128, 1024);
system("ps aux | grep boostHash | grep -v grep | awk '{print \"4. \" $5}'");
void *a = pool.malloc();
pool.free(a);
system("ps aux | grep boostHash | grep -v grep | awk '{print \"5. \" $5}'");
}
system("ps aux | grep boostHash | grep -v grep | awk '{print \"6. \" $5}'");
}
Output:
4. 18908
5. 19040
6. 18908
Which is fine, because:
a. I wanted to allocate 128 * 1024 = 131072 bytes, and got 19040 - 18908 = 132KB = 135168 bytes. 135168 - 131072 = 4096 bytes (that's just the pool over head, I think).
b. When the block ended, the memory was free'd.
destructor
int main() {
{
boost::pool<> *pool = new boost::pool<>(128, 1024);
system("ps aux | grep boostHash | grep -v grep | awk '{print \"7. \" $5}'");
void *a = pool->malloc();
pool->free(a);
delete pool;
system("ps aux | grep boostHash | grep -v grep | awk '{print \"8. \" $5}'");
}
system("ps aux | grep boostHash | grep -v grep | awk '{print \"9. \" $5}'");
}
Output:
7. 19040
8. 19040
9. 19040
This is strange,
a. For some reason, the size is already allocated (before I called pool.malloc().
b. The size isn't being free'd in delete.
Is this explainable?
Do I need to use another tool instead of ps to see the memory used by the program?
Is this explainable?
Yes.
Do I need to use another tool instead of ps to see the memory used by the program?
You are seeing the memory used by the program.
What you didn't take into account: memory allocation routines are heavily optimized. Libraries (like libc) will use various strategies to make allocation/reallocation faster, for various scenarios. Here are some common memory management strategies:
request memory preemptively, from the operating system; this allows the application to perform subsequent internal allocations of the same type, without the cost of requesting more memory from the OS;
caching released memory; this allows an applications to reuse memory (received from the OS) for subsequent allocations (and again, avoid the overhead of talking with the OS about it)
I have a following content in the file:
NAME=ALARMCARDSLOT137 TYPE=2 CLASS=116 SYSPORT=2629 STATE=U ALARM=M APPL=" " CRMPLINK=CHASSIS131 DYNDATA="GL:1,15 ADMN:1 OPER:2 USAG:2 STBY:0 AVAL:0 PROC:0 UKNN:0 INH:0 ALM:20063;1406718801,"
I just want to filter out NAME , SYSPORT and ALM field using sed
Try the below sed command to filter out NAME,SYSPORT,ALM fields ,
$ sed 's/.*\(NAME=[^ ]*\).*\(SYSPORT=[^ ]*\).*\(ALM:[^;]*\).*/\1 \2 \3/g' file
NAME=ALARMCARDSLOT137 SYSPORT=2629 ALM:20063
why not using grep?
grep -oE 'NAME=\S*|SYSPORT=\S*|ALM:[^;]*'
test with your text:
kent$ echo 'NAME=ALARMCARDSLOT137 TYPE=2 CLASS=116 SYSPORT=2629 STATE=U ALARM=M APPL=" " CRMPLINK=CHASSIS131 DYNDATA="GL:1,15 ADMN:1 OPER:2 USAG:2 STBY:0 AVAL:0 PROC:0 UKNN:0 INH:0 ALM:20063;1406718801,"'|grep -oE 'NAME=\S*|SYSPORT=\S*|ALM:[^;]*'
NAME=ALARMCARDSLOT137
SYSPORT=2629
ALM:20063
Here is another awk
awk -F" |;" -v RS=" " '/NAME|SYSPORT|ALM/ {print $1}'
NAME=ALARMCARDSLOT137
SYSPORT=2629
ALM:20063
Whenever there are name=value pairs in input files, I find it best to first create an array mapping the names to the values and then operating on the array using the names of the fields you care about. For example:
$ cat tst.awk
function bldN2Varrs( i, fldarr, fldnr, subarr, subnr, tmp ) {
for (i=2;i<=NF;i+=2) { gsub(/ /,RS,$i) }
split($0,fldarr,/[[:blank:]]+/)
for (fldnr in fldarr) {
split(fldarr[fldnr],tmp,/=/)
gsub(RS," ",tmp[2])
gsub(/^"|"$/,"",tmp[2])
name2value[tmp[1]] = tmp[2]
split(tmp[2],subarr,/ /)
for (subnr in subarr) {
split(subarr[subnr],tmp,/:/)
subName2value[tmp[1]] = tmp[2]
}
}
}
function prt( fld, subfld ) {
if (subfld) print fld "/" subfld "=" subName2value[subfld]
else print fld "=" name2value[fld]
}
BEGIN { FS=OFS="\"" }
{
bldN2Varrs()
prt("NAME")
prt("SYSPORT")
prt("DYNDATA","ALM")
}
.
$ awk -f tst.awk file
NAME=ALARMCARDSLOT137
SYSPORT=2629
DYNDATA/ALM=20063;1406718801,
and if 20063;1406718801, isn't the desired value for the ALM field and you just want some subsection of that, simply tweak the array construction function to suit whatever your criteria is.
Let's suppose I have this sample
foo/bar/123-465.txt
foo/bar/456-781.txt
foo/bar/102-445.txt
foo/bar/123-721.txt
I want to remove every line where the regex /[0-9]*- result also appears on another line. In other terms : I want to remove every line where the file prefix is present more than once in my file.
Therefore only keeping :
foo/bar/456-781.txt
foo/bar/102-445.txt
I bet sed can do this, but how ?
Ok I misunderstood your problem, here's how to do it:
grep -vf <(grep -o '/[0-9]*-' file | sort | uniq -d) file
In action:
cat file
foo/bar/123-465.txt
foo/bar/456-781.txt
foo/bar/102-445.txt
foo/bar/123-721.txt
grep -vf <(grep -o '/[0-9]*-' file | sort | uniq -d) file
foo/bar/456-781.txt
foo/bar/102-445.txt
awk '
match($0, "[0-9]*-") {
id=substr($0, RSTART, RLENGTH)
if (store[id])
dup[id] = 1
store[id] = $0
}
END {
for(id in store) {
if(! dup[id]) {
print store[id]
}
}
}
'
You can use the following awk script:
example.awk:
{
# Get value of interest (before the -)
prefix=substr($3,0,match($3,/\-/)-1)
# Increment counter for this value (starting at 0)
counter[prefix]++
# Buffer the current line
buffer[prefix]=$0
}
# At the end print every line which's value of interest appeared just once
END {
for(index in counter)
if(counter[index]==1)
print buffer[index]
}
Execute it like this:
awk -F\ -f example.awk input.file
How can I get all "clid's" which has the "client_type=0"? The pipe char "|" seperates each client info. The text, which I have is just one line:
clid=2 cid=3346 client_database_id=5153 client_nickname=xLukas\s\p\sLukas client_type=0|clid=3 cid=3346 client_database_id=1 client_nickname=powered\sby\sMirWayne.DE
client_type=1|clid=4 cid=3346 client_database_id=9661
client_nickname=Number\sone client_type=0|clid=5 cid=3469
client_database_id=1 client_nickname=powered\sby\sMirWayne
client_type=1|clid=6 cid=1716 client_database_id=1
client_nickname=FG\sBot client_type=1|clid=7 cid=3469
client_database_id=9661 client_nickname=Number\stwo
client_type=0|clid=8 cid=1762 client_database_id=4351
client_nickname=pr0zkillz1x\pTobi client_type=0|clid=9 cid=1764
client_database_id=5160 client_nickname=xL1mited\s/\sMax
client_type=0|clid=10 cid=1716 client_database_id=9704
client_nickname=Sebi client_type=0|clid=13 cid=3346
client_database_id=4336 client_nickname=checker284\s\p\sSebbo
client_type=0|clid=19 cid=1762 client_database_id=9312
client_nickname=pr0skillz1x\pDanie client_type=0|clid=30 cid=3346
client_database_id=9697 client_nickname=TeamSpeakUser
client_type=0|clid=33 cid=1716 client_database_id=1
client_nickname=serveradmin client_type=1
I need alle clid's, which has the client_type=0 in an extra line. For example like that:
clid=2
clid=3
clid=4
clid=5
...
My current solution is not working:
cat clientlist.txt | grep -Eo "clid=[0-9]+[\d\D]*client_type=0" | grep -Eo "clid=[0-9]+"
Can somebody help?
The pipe char "|" seperates each client info.
Making use of this information, you can say:
tr '|' '\n' < clientlist.txt | grep -Po 'clid=\d+(?=.*client_type=0)'
For your input, it'd result in:
clid=2
clid=4
clid=7
clid=8
clid=9
clid=10
clid=13
clid=19
clid=30
Using sed:
tr '|' '\n' < file | sed -n '/client_type=0/s/\(clid=[0-9]*\).*$/\1/p'
clid=2
clid=4
clid=7
clid=8
clid=9
clid=10
clid=13
clid=19
clid=30
Format:
[Headword]{}"UC(icl>restriction)"(Attributes);(gloss)
The testme.txt file has 2 lines
[testme] {} "acetify" (V,lnk,CJNCT,AJ-V,VINT,VOO,VOO-CHNG,TMP,Vo) <H,0,0>;
[newtest] {} "acid-fast" (ADJ,DES,QUAL,TTSM) <H,0,0>;
The expected output is this:
testme = acetify
newtest = acid-fast
What I have achieved so far is:
cat testme.txt | sed 's/[//g' | sed 's/]//g' | sed 's/{}/=/g' | sed 's/\"//'
testme = acetify" (V,lnk,CJNCT,AJ-V,VINT,VOO,VOO-CHNG,TMP,Vo) <H,0,0>;
newtest = acid-fast" (ADJ,DES,QUAL,TTSM) <H,0,0>;
How do I remove all the text from the second " to the end of the line?
Remove everything after the doublequote-space-openparenthesis " (:
sed 's/" (.*//g'
The whole process might be a little quicker with awk:
awk 'NF > 0 { print $1 " = " $3 }' testme.txt | tr -d '[]"'
this is how you do it with awk instead of all those sed commands, which is unnecessary. what you want is field 1 and field 3. use gsub() to remove the quotes and brackets
$ awk '{gsub(/\"/,"",$3);gsub(/\]|\[/,"",$1);print $1" = "$3}' file
testme = acetify
newtest = acid-fast
Your whole sequence of multiple calls to sed can be replaced by:
sed 's/\[\([^]]*\)][^"]*"\([^"]*\).*/\1 = \2/' inputfile