How to add a single special character randomly anywhere inside a string? Bash - linux

I have this script that generates a random character between 8-16. I am confused as to how I would add a single random special character from a bank [! # # $ % ^ & * ( ) _ + ] anywhere randomly inside this string?
if [ $# -eq 0 ] then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=(~ ! # # $ % ^ & * - +)
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
echo $str
exit 0
fi

teststring=foobarspam
specialchars='!##$%^&*()_+'
randomchar=${specialchars:RANDOM % ${#specialchars}:1}
randompos=$(( RANDOM % ( ${#teststring} + 1 ) ))
newstring=${teststring:0:randompos}${randomchar}${teststring:randompos}

You can use the following code.
#!/bin/bash
if [ $# -eq 0 ]; then
pwdlen=$(((RANDOM % 9 ) +8))
spclen=$((RANDOM % 1))
char=(0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V X W Y Z)
chars=('~' '!' '#' '#' '$' '%' '^' '&' '*' '-' '+')
#rand2=$random % 11
max=${#char[*]}
for i in `seq 1 $pwdlen`
do
let "rand=$RANDOM % $max"
str="${str}${char[$rand]}"
done
A=$(echo $str|wc -c) ## To get the count of
P=$((RANDOM % $A)) ## To get a random position of where to insert the character.
I=$((RANDOM % 11)) ## To get a random index number of chars array
C=${chars[$#]}
echo $str | sed 's!^\(.\{'$P'\}\).!\1\'"$C"'!' ## Inserting the special character to string in defined position
exit 0
fi
Output:
$ for i in `seq 1 10`;do ./test1;done
j^eh8BmD2H
0B01^1AN6EVw
Wu2$LLTILuDN8fSV
e^90gmHjksDo
eB7wa\#fmwf
NVAtJkmfqx~
JaHvD%uyO3rB
ncFrgyyz~UkZ
q0LLRHUNATM8DL
X%ARcXgyC1Do

I am not sure what script language are you using. I wrote a solution for you using PHP. If PHP is not what you are using, you should be able to convert the same logic to other languages and get the same results.
<?php
//This is the original string where you want to add a random character to
$org_string = 'This is My original String';
//calculates the length of the string
$org_length = strlen($org_string);
//find a random position
$pos = rand(0, $org_length-1);
//concatenate the first part of the string, random character, the remaining string
$final = substr($org_string, 0, $pos) . getOne() . substr($org_string, $pos);
//print the final value
echo $final;
//return a random string
function getOne(){
//the following string is 12 characters in length. it is all available characters that you want to select from
$str = '!##$%^&*()_+';
//return a random character
return $str[rand(0, 11)];
}
?>

Related

Does a second (inner) loop open a subprocess?

I have come to an interesting topic, while I was experimenting
recursive loops in a shell script.
First I came across interesting functionality of
for x in a b c d; do
for x in e f d h; do
a=test
done
echo $x
done
Always outputting letter h as variable $x. Which makes sense, as inner loop uses x as variable name too, and h would be the last one picked in such loop.
My concern is, does inner loops open a subprocess or how is the functionality guaranteed?
for x in a b c d; do
for x in e f d h; do
pstree $$
done
pstree $$
done
.. suggest in the output that no sub-processes are opened on nested loops.
I am probably a little bit stuck in a loop, but is there a good documentation how a shell operates loops? I would like to know how does shell interpret the loops so it's kept within one layer of instructions.
Modify your example in this way:
#! /bin/bash
set -x
for x in a b; do
: x=$x
for x in c d; do
: x=$x
a=test
done
echo $x
done
This outputs:
+ for x in a b
+ : x=a
+ for x in c d
+ : x=c
+ a=test
+ for x in c d
+ : x=d
+ a=test
+ echo d
d
+ for x in a b
+ : x=b
+ for x in c d
+ : x=c
+ a=test
+ for x in c d
+ : x=d
+ a=test
+ echo d
d
Now you can see, the inner loop modifies x after the outer loop. When you print x it has always the last value of the inner loop.

converting txt file to zip file in TCL

i convert zip binary file to base64 txt file using other code. Now I want to convert the base64 txt file back to zip file using below code. but the resultant zip file display error. How can I solve this
proc b64en str {
set bits $str
set tail {}
return [string map {
A 000000 B 000001 C 000010 D 000011 E 000100 F 000101
G 000110 H 000111 I 001000 J 001001 K 001010 L 001011
M 001100 N 001101 O 001110 P 001111 Q 010000 R 010001
S 010010 T 010011 U 010100 V 010101 W 010110 X 010111
Y 011000 Z 011001 a 011010 b 011011 c 011100 d 011101
e 011110 f 011111 g 100000 h 100001 i 100010 j 100011
k 100100 l 100101 m 100110 n 100111 o 101000 p 101001
q 101010 r 101011 s 101100 t 101101 u 101110 v 101111
w 110000 x 110001 y 110010 z 110011 0 110100 1 110101
2 110110 3 110111 4 111000 5 111001 6 111010 7 111011
8 111100 9 111101 + 111110 / 111111
} $bits]$tail
}
proc callme {file1 file2} {
set file1 [open $file1 r]
set file2 [open $file2 w+]
fconfigure $file2 -translation binary
fconfigure $file1 -buffering line
while {[gets $file1 data]>=0} {
set var $data
set nvar [string trimright $var = ]
set nvar [string trimright $nvar = ]
set var2 [b64en $nvar]
set var3 [binary format B* $var2]
puts $file2 $var3
}
close $file1
close $file2
}
set fp1 [lindex $argv 0]
set fp2 [lindex $argv 1]
callme $fp1 $fp2
The above code is working for txt to txt file
please help me.
Thanks
when in open resultant zip file it display this error
When you're writing binary data, I think you need to specify -nonewline, otherwise you'll have extra newline characters in the binary file, and the data will be corrupt.
puts -nonewline $file2 $var3

bash order-of-operations in math context: Wrong value assigned

Given the linux shell code,
~$ (( b = a, (a += 3) + $((a = 1)), b++ ))
~$ echo $b
2
Why does $b equal 2? I split the code into three steps:
~$ ((b = a))
~$ (((a += 3) + $((a = 1))))
~$ ((b++))
~$ echo $b
1
$b equals 1 this time, why?
P.S. Neither a nor b is initialized.
Your two examples are not equivalent. The arithmetic expansion $((...)) is performed before the (( ... )) statement is evaluated, so the following are equivalent:
(( b = a, (a += 3) + $((a = 1)), b++ ))
and
a=1
(( b = a, (a += 3) + a, b++ ))
Your attempt at breaking it into three parts is equivalent to
((b = a)) # b = 0 since uninitialized a is treated as 0
a=1
(((a += 3) + a))
((b++)) # b = 1
The difference is when, in the sequence of evaluation, a is first assigned the value of 1.
Because you set b = a, then bash waits for last assigning of a. In b will be assigned same value as the value assigned to a.
~$ (( b = a, (a += 3) + $((a = 5)), b++ ))
~$ echo $b
6
~$ echo $a
8
EDIT
1) column-separated expressions are treated sequentially
~$ echo $((1+1, 2+2, 3+3))
6
2) $((...)) expressions are treated first
which gives result:
(( b = a, (a += 3) + $((a = 1)), b++ ))
$((a = 1)) #a=1
b = a #a=b=1
a += 3 #a=4, b=1
b++ #a=4, b=2

while loop variable reading issue

I have a text file a.txt like this:
1 1 a
2 b
4 4 d
Now I read that text file and feed it into a while loop:
cat a.txt | while read k l o
do
echo " ${k} ${l} ${o} "
if [ "${k}" == "${l}" ]; then
echo " success ; X: ${k} Y : ${l} Z : ${o} "
else
echo " failed ; X: ${k} Y : ${l} Z : ${o} "
fi
done
In my text file 2nd line first value is empty. That's why I'm getting y value in to x and z value in to y.
How can I handle such empty values and get all values printed at their correct positions?
why don't you just insert 0 for empty x value?
anyway you would need 3 values.. /bin/sh read command assigns the first value to the first name..

How to assign letters of alphabet to numbers for Caesar cipher in Perl?

I wrote a program that encrypts the numbers corresponding to letters of an alphabet and decrypts it but how do I make it so that when I ask for input I assign each letter to it's number then do the operations and print the encryption and decryption of the message without several lines of code? This is my program:
print "Caesar's Cipher\n\n";
print "Reference:\n\n";
print "A B C D E F G H I J K L M\n";
print "0 1 2 3 4 5 6 7 8 9 10 11 12\n\n";
print "N O P Q R S T U V W X Y Z\n";
print "13 14 15 16 17 18 19 20 21 22 23 24 25\n";
print "\nEnter a Message (User numbers separated by space):\n";
$string = <>;
#sarray = split(" ",$string);
foreach $x (#sarray){
if ($x >=0 && $x <= 25){
$x = ($x+3)%26;
} else {
print "Entered incorrect message.\n";
die;
}
}
print "\nEncryption: \n";
print "#sarray\n";
foreach $x (#sarray){
if ($x >=0 && $x <= 25){
$x = ($x-3)%26;
} else {
print "Entered incorrect message.\n";
die;
}
}
print "Decryption: \n";
print "#sarray\n";
I want to be able to just input something like "HELLO" and then it will encrypt the message and decrypt it.
You have to consider upper and lower case, numeric digits, plus the space character and punctuation. Presently you handle only uppercase alpha. You need a hash that maps characters to numbers, and one that maps the other way.
$inputChar = character to be encoded
$charset = " ABCDEFGHI...Zabcdef...z0123456789!##$%^&*...";
$code = index($charset,$char);
# encode here as in your example using length($charset) instead of 26
$outputChar = substr($charset,$code,1);
Apply this logic to all the characters in your message to build the encrypted message.
The solution offered by Jim above exceeds what is being asked, since the OP only wants alphabet characters from A to Z. An easier way to implement this would be, taking J as an example search:
my #alpha = ('A'..'Z');
my $s = 'J';
my( $index ) = grep{ $alpha[ $_ ] eq $s } 0..$#alpha;

Resources