To introduce some randomness in my testbench I would like to use pseudo-random numbers seeded with the current Unix time or epoch. Is there a (non-synthesizable ofc) function in VHDL for that? I need it to work in VHDL 2008.
Why not simply passing a generic parameter value on the same command line you use to run the simulation? Example with bash:
entity foo is
generic(seed: natural := 0);
end entity foo;
architecture bar of foo is
begin
assert false report natural'image(seed);
end architecture bar;
$ ghdl -a --std=08 foo.vhd
$ ghdl -r --std=08 foo
foo.vhd:7:3:#0ms:(assertion error): 0
$ ghdl -r --std=08 foo -gseed=$(date +%s)
foo.vhd:7:3:#0ms:(assertion error): 1648027085
Related
I understand the following:
$ ruby -e "p 'abc'.sub('a','A').sub('b', 'B')"
"ABc"
I am OK with the following also:
echo abc | ruby -p -e "sub('a','A');sub('b', 'B')"
ABc
But:
echo abc | ruby -p -e "sub('a','A').sub('b', 'B')"
Abc
I expect the result to be "ABc" as well, why is it not? The second sub('b', 'B') is not operational.
The two cases look similar, but in fact you are running different methods from the Ruby core library in them:
In your first case, i.e. sub('a','A');sub('b', 'B'):
You are running both sub without specifying an explicit receiver, and therefore you are invoking the method Kernel#sub. The Ruby-Doc says about this method:
sub(pattern, replacement) → $_
Equivalent to $_.sub(args), except that $_ will be updated if substitution occurs. Available only when -p/-n command line option specified.
The following examples illustrate the differences with and without a receiver:
$ echo abc | ruby -p -e '$_.sub("a","A").sub("b", "B"); $_'
abc
$ echo abc | ruby -p -e 'sub("a","A").sub("b", "B"); $_'
Abc
Hence, in the first example, you really invoke that Kernel#sub twice, and after each invocation, $_ is updated. Therefore, $_ is ABc after the second sub has been executed. At the end of the of the whole expression supplied by -e (i.e. at the end of the implicit loop provided by the -p option), the value of $_ is printed, and you see ABc.
In your second example, i.e.
sub('a','A').sub('b', 'B')
The first sub again is Kernel#sub, as before. It has the effect of turning the string into Abc, and also sets $_ to Abc. However, the second sub now does have an explicit receiver (the string resulting from the first sub), and in this case, the method String#sub is executed. This method produces ABc, but different to Kernel#sub, it does not update $_. Therefore, $_ is still set to Abc, and this is what you see as output.
While it seems to be convenient to rely on the implicit effect certain methods have on $_, it is sometimes easier to make the manipulation explicit. For instance, if you do a
$_=$_.sub('a','A').sub('b','B')
you can clearly see what is going on. An alternative would be
$_.sub!('a','A');$_.sub!('b','B')
Note that in the last case, you do not want to chain the two sub!, because String#sub! returns nil if no substitutions have been performed.
Consider the following bash snippets. In them, I'm creating two associative arrays in different ways, and then printing one of the entries.
Scenario 1. Declaring and assigning in one statement. Works as expected:
make_person() { echo '([firstName]=Bob [lastName]=Black)'; }
declare -A person1=$(make_person)
echo "${person1[firstName]}"
Output:
Bob
Scenario 2. Declaring and assigning on two different lines. No output:
declare -A person2
person2=$(make_person)
echo "${person2[firstName]}"
Output:
Why does Scenario 1 succeed in printing the [firstName] entry while Scenario 2 does not? Are both scenarios defined and expected behaviour?
Because declare re-interprets and parses the arguments to detect ( ) in variable assignment and then do array assignments. Whereas in normal assignment var=anything is always a normal assignment, in var=(anything) the ( ) are detected when parsing the expression (when bash reads the line/input to execute). declare works more like eval, it re-evaluates the input.
What is the bash specific reason that Scenario 1 succeeds in printing the [firstName] entry, and Scenario 2 does not?
The "bash specific reason" is I guess it was programmed that way. The reason would be also to be compatible with POSIX, so that var=$(anything) should result in a normal variable as in POSIX.
Are both scenarios defined
"Defined" is a bit too much, I do not see much in bash documentation about this specific syntax, but
and expected behaviour?
Yes, this is working as expected.
Just to follow up on KamilCuk's excellent answer. This is really a comment but for the formatting.
To see the effect of declare -A person2; person2=$(make_person) use declare -p
$ declare -p person1 person2
declare -A person1=([lastName]="Black" [firstName]="Bob" )
declare -A person2=([0]="([firstName]=Bob [lastName]=Black)" )
To get this to "work", you need eval
$ eval "person2=$(make_person)"
$ declare -p person1 person2
declare -A person1=([lastName]="Black" [firstName]="Bob" )
declare -A person2=([lastName]="Black" [firstName]="Bob" )
But use the eval-like powers of declare as you discovered in the first form: declare -A ary=$(cmd)
As a complement to the already exhaustive answers you got:
If you are going to populate a Bash associative array from a function, you may as well benefit from the name reference feature from Bash v4.2+, with the added benefit, that it does not fork a sub-shell:
#!/usr/bin/env bash
make_person() {
local -n array=$1
# shellcheck disable=SC2034 # shellcheck cannot track nameref
array=([firstName]=Bob [lastName]=Black)
}
declare -A person1
make_person person1
declare -p person1
I saw there were several good answers for bash and even zsh(i.e. Here). Although I wasn't able to find a good one for fish.
Is there a canonical or clean one to prepend a string or a couple of lines into an existing file (in place)? Similar to what cat "new text" >> test.txt do for append.
As part of fish's intentional aim towards simplicity, it avoids syntactic sugar found in zsh. The equivalent to the zsh-only code <<< "to be prepended" < text.txt | sponge text.txt in fish is:
begin; echo "to be prepended"; cat test.txt; end | sponge test.txt
sponge is a tool from the moreutils package; the fish version requires it just as much as the zsh original did. However, you could replace it with a function easily enough; consider the below:
# note that this requires GNU chmod, though it works if you have it installed under a
# different name (f/e, installing "coreutils" on MacOS with nixpkgs, macports, etc),
# it tries to figure that out.
function copy_file_permissions -a srcfile destfile
if command -v coreutils &>/dev/null # works with Nixpkgs-installed coreutils on Mac
coreutils --coreutils-prog=chmod --reference=$srcfile -- $destfile
else if command -v gchmod &>/dev/null # works w/ Homebrew coreutils on Mac
gchmod --reference=$srcfile -- $destfile
else
# hope that just "chmod" is the GNU version, or --reference won't work
chmod --reference=$srcfile -- $destfile
end
end
function mysponge -a destname
set tempfile (mktemp -t $destname.XXXXXX)
if test -e $destname
copy_file_permissions $destname $tempfile
end
cat >$tempfile
mv -- $tempfile $destname
end
function prependString -a stringToPrepend outputName
begin
echo $stringToPrepend
cat -- $outputName
end | mysponge $outputName
end
prependString "First Line" out.txt
prependString "No I'm First" out.txt
For the specific case that file size is small to medium (fit in memory), consider using the ed program, which will avoid the temporary files by loading all data into memory. For example, using the following script. This approach avoid the need to install extra packages (moreutils, etc.).
#! /usr/env fish
function prepend
set t $argv[1]
set f $argv[2]
echo '0a\n$t\n.\nwq\n' | ed $f
end
I have a rename command as follows:
rename ".csv" "-en.csv" Daily_vills.csv
rename "^" "07302019" Daily*
when i run this, i get an error "rename: invalid option -- 'e'". I already tried "\-en.csv", but this results in "Daily_vills\-en.csv"
my question is how to make bash understand that -en is a replacement value and not a parameter.
original:
Daily_vills.csv
Target;
07302019Daily_vills-en.csv
Any help on this is greatly appreciated
Use -- to notify rename of end of options.
rename -- ".csv" "-en.csv" Daily_vills.csv
From posix utility conventions:
Guideline 10:
The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character.
It is common in many *nix tools to notify with -- the end of options. Examples:
# touch a file named -a
touch -- -a
# cat a file named -a
cat -- -a
# printf the string -b
printf -- -b
# find a string '-c' in files in current directory
grep -- -c *
The rename utility also follows the guideline from posix utility conventions. The -- may be used to notify rename of the end of options.
I have a 3rd party generator that's part of my build process (sbt native packager). It generates a bash script to be used to run my built program.
Problem is I need to use sh (ash), not bash. So the generator cranks out a line like this:
declare -a app_mainclass=("com.mypackage.Go")
sh chokes on this as there is no 'declare' command.
Clever me--I just added these lines:
alias declare=''
alias '-a'=''
This worked on all such declarations except this one--because of the parens. sh apparently has no arrays.
Given that I cannot practically change the generator, what can I do to spoof the sh code to behaving properly? In this case I logically want to eliminate the parens. (If I do this manually in the generated output it works great.)
I was thinking of trying to define a function app_mainclass= () { app_mainclass=$1; } but sh didn't like that--complained about the (. Not sure if there's a way to include the '=' as part of the function name or not.
Any ideas of a way to trick sh into accepting this generated command (the parens)?
I hesitate to suggest it, but you might try a function declaration that uses eval to execute any assignments produced by a declare statement. I might verify that the generated declare statements are "safe" before using this. (For example, that the assigned value doesn't contain any thing that might be executed as arbitrary code by eval.)
declare () {
array_decl=
for arg; do
# Check if -a is used to declare an array
[ "$arg" = -a ] && array_decl=1
# Ignore non-assignment arguments
expr "$arg" : '.*=.*' || continue
# Split the assignment into separate name and value
IFS='=' read -r name value <<EOF
$arg
EOF
# If it's an array assignment, strip the leading and trailing parentheses
if [ -n "array_decl" ]; then
value=${value#(}
value=${value%)}
fi
# Cross your fingers... I'm assuming `$value` was already quoted, as in your example.
eval "$name=$value"
done
}