sed group out of string and put it into variable - variables

Can you make it work?
result=${docker ps | sed -r 's/(.*)\s.*$/\1/'} && echo $result
Just want to pass the result of the seed into a variable (and print it out for debugging)
The tricky thing is, that docker ps returns multiple lines!
Update:
I changed It due to an post farther down to
result=$(docker ps | sed -r 's/(.*)\s.*$/\1/'} && echo "$result"
But this is the result:
root#Synobaby916:/volume1/Synology-Infrastructure/sys_scripts# result=$(docker ps | sed -r 's/(.*)\s.*$/\1/'} && echo "$result"
>
Behind the > is just a blinking cursor ...

To expand a variable it should be enclosed with double quotes "$result" or embraced with {} ${result}:
result=$(docker ps | sed -r 's/(.)\s.$/\1/') && echo "$result"
Here's a simplified analogy:
result=$(echo "hello there" | sed -rn 's/^([a-z]).*/\1/p') && echo "$result"
It'll output:
h (the first character of the string)

Related

Save expression to variable

I want to save the result of the expression to a variable. If I use echo it works but not with a variable
The version variable returns "Nextcloud 18.0.2"
version=$(sudo -u www php /usr/local/www/nextcloud/occ --version)
newversion=${version} | sed -e 's/Nextcloud //'
echo ${version} | sed -e 's/Nextcloud //'
returns "18.0.2"
echo $newversion returns a blank
You're missing the echo and a command substitution $(...):
newversion=$(echo "$version" | sed 's/Nextcloud //')
or you could use a parameter expansion to remove the shortest prefix pattern
newversion=${version#Nextcloud }

using sed to add a backslash in front of a variable

I have a variable and that variable only needs a '\' in front of it.
I would say that the sed command is the ideal tool for it?
I tried using single quotes, double quotes, multiple variables, combination of variables, ...
I don't get an error returned but the end result is not showing what I need it do be
FOLDER=$(echo `cat file.XML | grep "Value" | cut -d \" -f2`)
echo $FOLDER
sed -i "s#"$FOLDER"#"\\$FOLDER"#g" ./file.XML
echo $FOLDER
After execution, I get
$ ./script.sh
b4c17422-1365-4fbe-bccd-04e0d7dbb295
b4c17422-1365-4fbe-bccd-04e0d7dbb295
Eventually I need to have a result like
$ ./script.sh
b4c17422-1365-4fbe-bccd-04e0d7dbb295
\b4c17422-1365-4fbe-bccd-04e0d7dbb295
Fixed thanks to the input of Cyrus and Ed Morton.
FOLDER=$(echo `cat file.XML | grep "Value" | cut -d \" -f2`)
NEW_FOLDER="\\$FOLDER"
sed -i "s#$FOLDER#\\$NEW_FOLDER#g" ./file.XML

How do I correctly retrieve, using bash' cut, the first field from a line with only 1 field in a text file?

In a text file (accounts.txt) with (financial) accounts the sub-accounts are, and need to be, separated by an underscore, looking like this:
assets
assets_hh
assets_hh_reimbursements
assets_hh_reimbursements_ff
... etc.
Now I want to get specific sub-accounts from specific line numbers, e.g.:
field 3 from line 4:
$ lnr=4; fnr=3
$ cut -d $'\n' -f "$lnr" < accounts.txt | cut -d _ -f "$fnr"
reimbursements
$
But both fnr=1 and fnr=2 give for the first line, which has only 1 field:
$ cut -d $'\n' -f 1 < accounts.txt | cut -d _ -f "fnr"
assets
$
which is undesired behaviour.
Now I can get around this by prefixing an underscore to each account and add 1 to each required field number, but this is not an elegant solution.
Am I doing something wrong and/or can this be changed by issuing a different retrieval command?
Using the cut -d $'\n' -f "$lnr" for getting the lnr-th line from the file is somewhat strange. More common approach is using sed, like:
sed -n "${lnr}p" file | cmd ...
However, for this the awk is better - in one invocation could handle the lnr and fnr too.
file=accounts.txt
lnr=1
fnr=2
awk -F_ -v l=$lnr -v f=$fnr 'NR==l{print $f}' "$file"
The above for the all combinations lnr/fnr produces:
line field1 field2 field3 field4
------------------------------------------------------------------------
assets assets
assets_hh assets hh
assets_hh_reimbursements assets hh reimbursements
assets_hh_reimbursements_ff assets hh reimbursements ff
Check below solution -
cat f
assets
assets_hh
assets_hh_reimbursements
assets_hh_reimbursements_ff
Based on your comment try below commands -
$ lnr=1; fnr=2
$ echo $lnr $fnr
1 2
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
###Output is nothing as line 1 column 2 is blank when FS="_"
$ lnr=4;fnr=1
$ echo $lnr $fnr
4 1
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
assets
$ lnr=4;fnr=3
$ echo $lnr $fnr
4 3
$ awk -v lnr=$lnr -v fnr=$fnr -F'_' 'NR==lnr {print $fnr}' f
reimbursements
One solution is to head|tail and read into an array so it's easier to work with the items:
lnr=4
fnr=2
IFS=_ read -r -a arr < <(head -n "$lnr" accounts.txt | tail -n 1)
#note that the array is 0-indexed, so the fieldnumber has to fit that
echo "${arr[$fnr]}"
Then you could expand the idea into a more usable function:
get_field_from_file() {
local fname="$1"
local lnr="$2"
local fnr="$3"
IFS=_ read -r -a arr < <(head -n "$lnr" "$fname" | tail -n 1)
if (( $fnr > ${#arr[#]} )); then
return 1
else
echo "${arr[$fnr]}"
fi
}
field=$(get_field_from_file "accounts.txt" "4" "2") || echo "no such line or field"
[[ -n $field ]] && echo "field: $field"

How to replace a string in a file in KSH

My KSH-Script should replace a String in a txt file from the same directory.
sed -i 's/"$original"/"$reversed"/' inputtext.txt
is what I'm using currently, but it doesn't work. There is no error in the code or things like that. It just doesn't work.
Here is my whole code:
#!/bin/ksh
original=$1
reversed=""
counter=0
echo $original | awk -v ORS="" '{ gsub(/./,"&\n") ; print }' | \
while read char
do
letters[$counter]+="$char"
((counter=counter+1))
done
length=${#original}
((length=length-1))
echo $original | awk -v ORS="" '{ gsub(/./,"&\n") ; print }' | \
while read char
do
reversed+=${letters[$length]}
((length=length-1))
done
echo $reversed
sed -i 's/"$original"/"$reversed"/' inputtext.txt
exit 0
I want, that in the file "inputtext.txt" (same dir as the .sh file) every word that equals "$original" gets changed to "$reversed".
What am I doing wrong?
I think single quotes prevent variable expansion. You can try this:
sed -i "s/$original/$reversed/" inputtext.txt

How do you change a variable in a KSH if or case statement?

Does anyone know how to set a variable with global scope in a KSH if, case, or loop statement?
I am trying to run the following code but the script only echo's "H" instead of the actual value seen in the input file.
CFG_DIR=${WORK_DIR}/cfg
CFG_FILE=${CFG_DIR}/$1
NAME=$(echo $CFG_FILE | cut -f1 -d\.)
UPPER_BUS_NETWORK="H"
cat ${CFG_FILE} | grep -v ^\# |
while read CLINE
do
PROPERTY=$(echo $CLINE | cut -f1 -d\=)
VALUE=$(echo $CLINE | cut -f2 -d\=)
if [ ${PROPERTY} = "UpperBusService" ]; then
UPPER_BUS_SERVICE="${VALUE}"
fi
if [ ${PROPERTY} = "UpperBusNetwork" ]; then
UPPER_BUS_NETWORK="${VALUE}"
fi
done
echo ${UPPER_BUS_NETWORK}
Are you sure you're running that in ksh? Which version? Ksh93 doesn't set up a subshell in a while loop. Bash, dash, ash and pdksh do, though. I'm not sure about ksh88.
Compare
$ bash -c 'a=111; echo foo | while read bar; do echo $a; a=222; echo $a; done; echo "after: $a"'
111
222
after: 111
to
ksh -c 'a=111; echo foo | while read bar; do echo $a; a=222; echo $a; done; echo "after: $a"'
111
222
after: 222
Zsh gives the same result as ksh93.
Unfortunately, pdksh doesn't support process substitution and ksh93 does, but not when redirected into the done of a while loop, so the usual solution which works in Bash is not available. This is what it would look like:
# Bash (or Zsh)
while read ...
do
...
done < <(command)
Using a temporary file may be the only solution:
command > tmpfile
while read
do
...
done < tmpfile
Some additional notes:
Instead of cat ${CFG_FILE} | grep -v ^\# do grep -v ^\# "${CFG_FILE}"
Usually, you should use read -r so backslashes are handled literally
Instead of NAME=$(echo $CFG_FILE | cut -f1 -d\.) you should be able to do something like NAME=${CFG_FILE%%.*} and VALUE=${#*=}; VALUE=${VALUE%%=*}
Variables should usually be quoted on output, for example in each of your echo statements and your cat command
I recommend the habit of using lowercase or mixed case variable names to avoid conflict with shell variables (though none are present in your posted code)