Rare behaviour in command line arguments - c++

I am trying to write a program in cpp using maps...
My goal is to allow * alone when we pass via comand line argument
And i have to restrict the characters coming along with * (ie)abc and abc
int main(int argc,char *argv[])
{
prinf("%s\n",argv[1]);
char str[256] = "";
int length;
strcpy(str,argv[1]);
length = strlen(str);
if((str[0] = '*' )&& (length == 1))
printf("success\n");
else
printf("failure");
return 0;
}
when i run this program ,getting the following output
$ ./exec *
$ 1
$ failure
argv[1] = 1(printing 1 instead of *)
failure because of not getting * as input argument,it results in failure.
Could someone help me to solve this issue?

Items on the command line are processed by the shell.
In the shell, the * performs a glob operation
In general, a glob operator, when standing alone, will result in a list of all the files in the current directory.

The character * has a special meaning in most shells. Your shell expands it to the files in the current directory resulting in a completely different arguments than the one you intended.
To avoid this, you can do:
$ ./exec "*"
or
$ ./exec '*'
If your shell is bash, then you can also turn off the globbing expansion with:
$ set -o noglob
or
$ set -f
but I would suggest the former options (above) as it's "minimal" and doesn't affect your shell's default behaviour otherwise.

Related

How to pass a string to omnetpp simulation from the command prompt

In my .ned file I have a simple module
simple Txc1
{
parameters:
int dummy_number = default(10);
}
When I run the simulation from the command prompt by specifying dummy_number I want i.e.,
opp_run -l tictoc omnetpp.ini --**.dummy_number=15
dummy_number equals 15 in my simulation.
But when instead of integer I want to specify a string
simple Txc1
{
parameters:
string dummy_string = default("Some dummy string");
}
opp_run -l tictoc omnetpp.ini --**.dummy_string="Test"
I get the following error
Cannot evaluate parameter 'dummy_string':(omnetpp::cModule)Tictoc1: unknown parameter 'Test' -- in module (Txc1) Tictoc1.tic (id=2), during network setup
Why my string is perceived as a parameter when it is just a value and how do I circumvent the problem?
Thanks
As long as your string does not contain a space, add backslashes before quotes, i.e.:
opp_run -l tictoc omnetpp.ini --**.dummy_string=\"TestWithoutSpace\"

How to write unix regular expression to select for specific files in a cp for-loop

I've got a directory with a bunch of files. Instead of describing the filenames and extensions, I'll just show you what is in the directory:
P01_1.atag P03_3.tgt P05_6.src P08_3.atag P10_5.tgt
P01_1.src P03_4.atag P05_6.tgt P08_3.src P10_6.atag
P01_1.tgt P03_4.src P06_1.atag P08_3.tgt P10_6.src
P01_2.atag P03_4.tgt P06_1.src P08_4.atag P10_6.tgt
P01_2.src P03_5.atag P06_1.tgt P08_4.src P11_1.atag
P01_2.tgt P03_5.src P06_2.atag P08_4.tgt P11_1.src
P01_3.atag P03_5.tgt P06_2.src P08_5.atag P11_1.tgt
P01_3.src P03_6.atag P06_2.tgt P08_5.src P11_2.atag
P01_3.tgt P03_6.src P06_3.atag P08_5.tgt P11_2.src
P01_4.atag P03_6.tgt P06_3.src P08_6.atag P11_2.tgt
P01_4.src P04_1.atag P06_3.tgt P08_6.src P11_3.atag
P01_4.tgt P04_1.src P06_4.atag P08_6.tgt P11_3.src
P01_5.atag P04_1.tgt P06_4.src P09_1.atag P11_3.tgt
P01_5.src P04_2.atag P06_4.tgt P09_1.src P11_4.atag
P01_5.tgt P04_2.src P06_5.atag P09_1.tgt P11_4.src
P01_6.atag P04_2.tgt P06_5.src P09_2.atag P11_4.tgt
P01_6.src P04_3.atag P06_5.tgt P09_2.src P11_5.atag
P01_6.tgt P04_3.src P06_6.atag P09_2.tgt P11_5.src
P02_1.atag P04_3.tgt P06_6.src P09_3.atag P11_5.tgt
P02_1.src P04_4.atag P06_6.tgt P09_3.src P11_6.atag
P02_1.tgt P04_4.src P07_1.atag P09_3.tgt P11_6.src
P02_2.atag P04_4.tgt P07_1.src P09_4.atag P11_6.tgt
P02_2.src P04_5.atag P07_1.tgt P09_4.src P12_1.atag
P02_2.tgt P04_5.src P07_2.atag P09_4.tgt P12_1.src
P02_3.atag P04_5.tgt P07_2.src P09_5.atag P12_1.tgt
P02_3.src P04_6.atag P07_2.tgt P09_5.src P12_2.atag
P02_3.tgt P04_6.src P07_3.atag P09_5.tgt P12_2.src
P02_4.atag P04_6.tgt P07_3.src P09_6.atag P12_2.tgt
P02_4.src P05_1.atag P07_3.tgt P09_6.src P12_3.atag
P02_4.tgt P05_1.src P07_4.atag P09_6.tgt P12_3.src
P02_5.atag P05_1.tgt P07_4.src P10_1.atag P12_3.tgt
P02_5.src P05_2.atag P07_4.tgt P10_1.src P12_4.atag
P02_5.tgt P05_2.src P07_5.atag P10_1.tgt P12_4.src
P02_6.atag P05_2.tgt P07_5.src P10_2.atag P12_4.tgt
P02_6.src P05_3.atag P07_5.tgt P10_2.src P12_5.atag
P02_6.tgt P05_3.src P07_6.atag P10_2.tgt P12_5.src
P03_1.atag P05_3.tgt P07_6.src P10_3.atag P12_5.tgt
P03_1.src P05_4.atag P07_6.tgt P10_3.src P12_6.atag
P03_1.tgt P05_4.src P08_1.atag P10_3.tgt P12_6.src
P03_2.atag P05_4.tgt P08_1.src P10_4.atag P12_6.tgt
P03_2.src P05_5.atag P08_1.tgt P10_4.src
P03_2.tgt P05_5.src P08_2.atag P10_4.tgt
P03_3.atag P05_5.tgt P08_2.src P10_5.atag
P03_3.src P05_6.atag P08_2.tgt P10_5.src
I have a file that is just outside of this directory that I need to copy to all of the files that end with "_1.src" inside the directory.
I'm working with unix in the Terminal app, so I tried writing this for loop, but it rejected my regular expression:
for .*1.src in ./
> do
> cp ../1.src
> done
I've only written regular expressions in Python before and have minimal experience, but I was under the impression that .* would match any combination of characters. However, I got the following error message:
-bash: `.*1.src': not a valid identifier
I then tried the same for loop with the following regular expression:
^[a-zA-Z0-9_]*1.src$
But I got the same error message:
-bash: `^[a-zA-Z0-9_]*1.src$': not a valid identifier
I tried the same regular expression with and without quotation marks, but it always gives the same 'not a valid identifier' error message.
Tested on Bash 4.4.12, the following is possible:
$ for i in ./*_1.src; do echo "$i" ; done
This will echo every file ending with _1.src to the screen, thus moving it will be possible as well.
$ mkdir tmp
$ for i in ./*_1.src; do mv "$i" tmp/.; done
I've tested with the following data:
$ touch P{1,2}{0,1,2}_{0..6}.{src,tgt,atag}
$ ls
P10_0.atag P10_5.src P11_3.tgt P12_2.atag P20_0.src P20_5.tgt P21_4.atag P22_2.src
P10_0.src P10_5.tgt P11_4.atag P12_2.src P20_0.tgt P20_6.atag P21_4.src P22_2.tgt
P10_0.tgt P10_6.atag P11_4.src P12_2.tgt P20_1.atag P20_6.src P21_4.tgt P22_3.atag
P10_1.atag P10_6.src P11_4.tgt P12_3.atag P20_1.src P20_6.tgt P21_5.atag P22_3.src
P10_1.src P10_6.tgt P11_5.atag P12_3.src P20_1.tgt P21_0.atag P21_5.src P22_3.tgt
P10_1.tgt P11_0.atag P11_5.src P12_3.tgt P20_2.atag P21_0.src P21_5.tgt P22_4.atag
P10_2.atag P11_0.src P11_5.tgt P12_4.atag P20_2.src P21_0.tgt P21_6.atag P22_4.src
P10_2.src P11_0.tgt P11_6.atag P12_4.src P20_2.tgt P21_1.atag P21_6.src P22_4.tgt
P10_2.tgt P11_1.atag P11_6.src P12_4.tgt P20_3.atag P21_1.src P21_6.tgt P22_5.atag
P10_3.atag P11_1.src P11_6.tgt P12_5.atag P20_3.src P21_1.tgt P22_0.atag P22_5.src
P10_3.src P11_1.tgt P12_0.atag P12_5.src P20_3.tgt P21_2.atag P22_0.src P22_5.tgt
P10_3.tgt P11_2.atag P12_0.src P12_5.tgt P20_4.atag P21_2.src P22_0.tgt P22_6.atag
P10_4.atag P11_2.src P12_0.tgt P12_6.atag P20_4.src P21_2.tgt P22_1.atag P22_6.src
P10_4.src P11_2.tgt P12_1.atag P12_6.src P20_4.tgt P21_3.atag P22_1.src P22_6.tgt
P10_4.tgt P11_3.atag P12_1.src P12_6.tgt P20_5.atag P21_3.src P22_1.tgt P10_5.atag
P11_3.src P12_1.tgt P20_0.atag P20_5.src P21_3.tgt P22_2.atag
Apparently, my previous answer didn't work. But this seems to:
$ for x in `echo ./P[01][012]_1.src`; do echo "$x"; done
./P01_1.src
./P02_1.src
So, when you run this echo alone, this pattern gets expanded into many names:
$ echo ./P[01][012]_1.src # note that the 'regex' is not enclosed in quotes
./P01_1.src ./P02_1.src
And then you can iterate over these names in a loop.
BTW, as noted in the comments, you don't even need that echo, so you can plug the pattern right into the loop:
for x in ./P[01][012]_1.src; do echo "$x"; done
Please correct me if your goal is something other than
"overwrite many existing files sharing a common suffix with the contents of a single file"
find /path/to/dest_dir -type f -name "*_1.src" |xargs -n1 cp /path/to/source_file
Note that without the -maxdepth 1 option, find will recurse through your destination directory.
Thanks to everyone; this is what ended up working:
for x in `echo ./P[0-9]*_1.src`
> do
> cp ../1.src "$x"
> done
This loop allowed me to copy the contents of the one file to all of the files in the subdirectory that ended with "_1.src"

Regex syntax error with Sed command in Ubuntu 9.04

I have the sed command like this:
radius_clientsfile=clients.conf
iface_netsize="/64"
wireless_prefix=fd04:bd3:80e8:3::
sed -i "/client $wireless_prefix\\$iface_netsize/ {n s/\(\W*secret\W*=\W\).*/\1$key/}" $radius_clientsfile
clients.conf has the content like this:
client fd04:bd3:80e8:3::/64 {
secret = 00000000000000000000000000000001
}
which aim to replace value of secret by key in clients.conf file. For Example, if key is 00000000000000000000000000000002, the content of clients.conf should be changed as following:
client fd04:bd3:80e8:3::/64 {
secret = 00000000000000000000000000000002
}
This script work on OpenWRT attitude adjustment r35400 for armv5tejl
However, it can not work in Ubuntu 9.04 with error:
sed: -e expression #1, char 36: extra characters after command
Could anyone help me for this situation?
I think you need add a ; between command n and command s, like this
sed -i "/client $wireless_prefix\\$iface_netsize/ {n; s/\(\W*secret\W*=\W\).*/\1$key/}" $radius_clientsfile
This working in my cygwin environment.
You need to separate the commands in the command block with a semi-colon, so add a ; after the n command to separate it from the following command.
Like this:
{n;s/\(\W*secret\W*=\W\).*/\1$key/}

Audit bash commands for bash RPG

I want to be able to write a program that when you type in commands, it will do things like count the amount of times you've used cd. Something similar to this:
[ : ~ $] cd public_html
Congratulations! You've earned the Badge 'cd master!'. Level up!
All my C++ file consists of so far is:
#include <iostream>
int main(int argc, char* argv[]) {
int counter = 0;
for (int i = 1; i < argc; i++) {
std::cout << argv[i] << std::endl;
if (argv[i] == "cd")
std::cout << "Badge earned 'cd master!' +5120 experience points" << std::endl;
}
return 0;
}
As it reflects one attempted solution involving:
#!/bin/sh
bash | tee ./main
and
bind 'RETURN: "echo $(!!) | tee ~/.main \n"'
I've decided to go with
export PROMPT_COMMAND='history | tail -n1'
But that would mean having to parse the output.
What's the easiest way of accomplishing this?
edit
Here's what I've managed to produce:
#!/bin/sh
export COUNTER=0
export MAXWIDTH=10
export TNL=1000
update_prompt() {
export PS1="> "
}
cd() {
COUNTER=$(($COUNTER + 25));
echo +25;
builtin cd $#;
}
help() {
echo "custom commands are: score";
}
score() {
echo $COUNTER"/"$TNL
BAR=$(yes "#" | head -n 10 | tr -d '\n')
OVERLAY=$(yes "%" | head -n 10 | tr -d '\n')
WIDTH=$(echo "$COUNTER*$MAXWIDTH/$TNL" | bc)
FIRST=${BAR:0:WIDTH}
SECOND=${OVERLAY:0:$((MAXWIDTH-WIDTH))}
echo "["$FIRST$SECOND"]"
}
exit() {
echo "Bye bye";
builtin exit $#;
}
export -f update_prompt
export -f cd # export the function
export -f help
export -f score
export -f exit
bash # run subshell with the exported functions
update_prompt
An easy solution is to overwrite the cd command of your shell inside the shell itself. For example, in Bash or ZSH:
cd() {
echo "Congratulations";
builtin cd $#;
}
(This is for example used in projects like autoenv.)
You can do the same for all other commands. You can also call your C++ code from there.
If you want to put that into a script, e.g. name it learn-bash.sh:
cd() { ... }
export -f cd # export the function
bash # run subshell with the exported functions
Another solution, where you have much more power, but which is way more involved: take the source code of Bash (it's C) and extend it (by C or C++). Then you can basically do whatever you want. And you have everything directly there, i.e. the parsed commands, etc.
After every command COMMAND_PROMPT is executed within bash. You could use that with history to see the last command used.
You can read here on how PS1, PS2, PS3 and COMMAND_PROMPT work in bash.
There are a few answers on exactly this question already on SO:
How can I intercept commands that contain a certain string?
bash: how to intercept every command
bash: How to intercept command line and do various actions based on the contents?
I've done something similar a while ago, and here's the solution I've found.
You want to add the following lines to .bashrc:
hook() {
whatever "$#"
}
invoke_hook() {
[ -n "$COMP_LINE" ] && return
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return
local command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
hook "$command"
}
trap 'invoke_hook' DEBUG
Replace whatever with your C++ program. This will execute your hook before each command, and will pass the original command as the arguments.

Perl: suppress output of backtick when file not found

In my code :
$status = `ls -l error*`;
It shows output : ls *error No such file or directory.
How can I suppress this message. I am interested in determining that the error files are generated or not. If yes, I need the list of files else ignore (without printing the message)
By running it like
$status = `ls -l error* 2> /dev/null`;
and suppressing the external command's output to standard error.
If you just need the file names (and not all the other info that ls's -l switch gives you), this can be accomplished in pure Perl with a statement like
#files = glob("error*");
if (#files == 0) {
... there were no files ...
} else {
... do something with files ...
}
and if you do need all the other info you get from ls -l ..., applying the builtin stat function to each file name can give you the same information.