I have a file:
AA BB CC DD
BB CC DD AA
BB CC DDA AA
CC DD AA BB
This command prints the line:
$ awk '{if($3=="DD") print}' file
BB CC DD AA
I want this condition to write to the array. This command does not work:
$ awk '{if($3=="DD") split($0, a, RS); print a[1]}' file
BB CC DD AA
BB CC DD AA
BB CC DD AA
Thank you for your help.
EDIT:
I wanted to write to an array of lines from the pattern 'DD'.
These are good solutions:
awk '{if($3=="DD") {split($0, a, RS); print a[1];}}' file
awk '$3=="DD"{split($0, a, RS); print a[1];}' file
Thank you for your help.
You're printing the result regardless of whether $3 == "DD", which seems unlikely to be what you want.
You're also splitting with RS which is not set here so for sample output, compare:
awk '{if($3=="DD") {split($0, a); print a[1];}}' file
which splits with FS instead (hence prints just BB for the above).
I'm not completely clear on what you want to do, but try this:
awk '$3 == "DD" { print $1 }' file
The manual splitting you're doing is unneeded in awk.
Related
I want to merge multiple file that I create on function call, because I call three time the function on Main
aa_file
aa
bb_file
bb
cc_file
cc
Final output
final_file
aa
bb
cc
function cal () {
# Some operation
while true; do
read -p "would you like asignment ? on ${var} " yn
case $yn in
[Yy]* ) arr_var+=("$var"); echo "$var" > $var_file;
[Nn]* ) break;;
* ) echo "Please answer yes or no.";;
esac
# Some operation
done
}
# Main
eval arr_var=()
cal "aa"
cal "bb"
cal "cc"
How make a function that can merge all file
for i in "${arr_var[#]}"
do
cat $i_file $(i+1)_file > final_file
done
because, when I call only two times the function cal, that I want
# Main
eval arr_var=()
cal "aa"
cal "cc"
final_file
aa
cc
Please correct your question, because it is hard to find out what you want.
However, you can call a function multiple times, and you can merge its output into another file. Like this:
for f in `seq 1 5`
do
cat ${f}
done > output_file
Or even like this:
(
cal "aa"
cal "bb"
cal "cc"
) > output_file
In your version, the final_file gets overwritten in every iteration:
for i in "${arr_var[#]}"
do
cat $i_file $(i+1)_file > final_file
done
Either change > to >> or move the > outside the loop.
if you use bash, you can do:
arr_var=(aa bb cc)
cat "${arr_var[#]/%/_file}" > final_file
Assume That we have a directory name "A" with 4 sub directories(aa,bb,cc,dd), some of the sub directories also have sub directories, so assume a schematic like below:
A
aa
aaa
bb
bbb
bbbb
cc
dd
I tried to list the sub directories(aa,bb,cc,dd) in an array and then use them in my script by their array number.
I used the script below for copying dd to parent directory:
while IFS= read -d '' file; do
A+=( "$file" )
done < <(find . -type d -print0 | LC_ALL=C sort -z)
cp -r `pwd`/${A[4]}" `pwd`/..
But the problem is that the script make an array of all of the sub-directories, [aa aaa bb bbb bbbb cc dd]
so ${a[4]} = bbb and not dd.
Any idea how to fix it?
You can restrict find to just look at the top directory, with the maxdepth option:
find . -type d -print0 -maxdepth 1 | LC_ALL=C sort -z
You can achieve the same thing in a simpler way using a glob:
dirs=(*/) # store all top level directories into the dirs array
dirs=("${dirs[#]%/}") # strip trailing / from each element of the array
and then
cp -r "$PWD/${dirs[4]}" "$PWD/.."
Double quotes are needed to prevent word splitting and globbing
pwd in backquotes can simply be written as $PWD, which doesn't need to create a subshell
I am new to Shell scripting. I've requriment to replace few string values in a file. They have to be read from command line and shell script looks like below.
test.sh --old-value yahoo.com --new-value ibibo.io --old-value xxxxxx --new-value yyy --exclude aa bb cc
Now, I want read --old-values into one array, --new-values into other array and --exclude into another array.
i am trying below approach.
while [[ $# -gt 1 ]]
do
key="$1"
case $key in
--old-value)
OLDVALUE="$2"
shift # past argument
;;
--new-value)
NEWVALUE="$2"
shift # past argument
;;
--exclude)
EXCLUDEFILETYPES=("$#")
shift
;;
*)
# unknown option
;;
esac
shift # past argument or value
done
But this read the old value into OLDVALUE. I have to read both --old-values into an array.
Can someone help on how to achieve this usecase?
#!/bin/bash
# declare arrays
old=(); new=(); exclude=()
while [[ $# -gt 1 ]]; do
key="$1"
value="$2"
[[ $key == --old-value ]] && old+=("$value")
[[ $key == --new-value ]] && new+=("$value")
[[ $key == --exclude ]] && shift && exclude+=("$#")
shift 2
done
# show content of arrays
declare -p old new exclude
I assume --exclude aa bb cc are last arguments.
Example: ./test.sh --old-value yahoo.com --new-value ibibo.io --old-value xxxxxx --new-value yyy --exclude aa bb cc
Output:
declare -a old='([0]="yahoo.com" [1]="xxxxxx")'
declare -a new='([0]="ibibo.io" [1]="yyy")'
declare -a exclude='([0]="aa" [1]="bb" [2]="cc")'
Another variant:
while (( $# )); do
case "$1" in
--old-value) old+=("$2") ;;
--new-value) new+=("$2") ;;
--exclude) shift; exc=("$#") ; break ;;
--*) echo "bad arg" ; exit 1 ;;
esac
shift;shift
done
printf "old: %s\n" "${old[#]}"
printf "new: %s\n" "${new[#]}"
printf "exc: %s\n" "${exc[#]}"
output
old: yahoo.com
old: xxxxxx
new: ibibo.io
new: yyy
exc: aa
exc: bb
exc: cc
Of course, this still has problems. For example if the script is called as
--old-value yahoo.com --new-value --old-value xxxxxx --new-value yyy --exclude aa bb cc
note the missing new value argument. In such case the result will be of course wrong...
old: yahoo.com
new: --old-value
exc:
handling such error cases needs much more complicated state-handling.
I am trying to store the variables $d, $tf_name, $db_orig created in the following loop to a file.I want to end up with a tab separated MY_FILE.txt containing the following fields $d, $tf_name, $db_orig and each iteration of this set of variables to be stored in a new line in the file MY_FILE.txt.
MY_ARRAY=()
for d in */
do
IN=$d
folderIN=(${IN//_/ })
tf_name=${folderIN[-1]%/*}
db_orig=${folderIN[-2]%/*};
ENTRY="$d\t$tf\t$id\t$db_orig\n"
MY_ARRAY+=$ENTRY
done
$MY_ARRAY > MY_FILE.txt
It doesn't recognise \t and \n as TAB and NEWLINE respectively. It stores all the values next to each other in the same line without TAB, in the array MY_ARRAY.
Any help?
Yes, this happens because $MY_ARRAY > MY_FILE.txt is not a valid command.
You need to print your array to the file.
And in order to print it correctly you need either to use
echo -e "${MY_ARRAY[#]}" >file or printf
By man echo
echo -e : enable interpretation of backslash escapes
Moreover, if you need to store the $ENTRY to your array you need to do it like this:
MY_ARRAY+=("$ENTRY")
In any case, you can do it without the need of an array. You can just apply += in the ENTRY : ENTRY+="$d\t$tf\t$id\t$db_orig\n"
Test:
$ e+="a\tb\tc\td\n"
$ e+="aa\tbb\tcc\tdd\n"
$ e+="aaa\tbbb\tccc\tddd\n"
$ echo -e "$e"
a b c d
aa bb cc dd
aaa bbb ccc ddd
# Test with array
$ e="a\tb\tc\td\n" && myar+=("$e")
$ e="aa\tbb\tcc\tdd\n" && myar+=("$e")
$ e="aaa\tbbb\tccc\tddd\n" && myar+=("$e")
$ echo -e "${myar[#]}"
a b c d
aa bb cc dd
aaa bbb ccc ddd
#Alternative array printing
$ for i in "${myar[#]}";do echo -en "$i";done
a b c d
aa bb cc dd
I got the following code. I would like to make cc dd ee ff as array [2]
keyvariable="aa bb cc dd ee ff"
while read -a line;
do
a=$(echo "${line[0]}")
b=$(echo "${line[1]}")
c=$(echo "${line[2]}")
done <<< "$keyvariable"
echo "$a $b $c"
current output:
aa bb cc
I would like to have the following output, where aa is [0] bb is [1] and cc dd ee is [2]
aa bb cc dd ee
You don't need the while loop here at all.
You don't want to use read with the -a switch at all here. Instead you want:
read -r a b c <<< "$keyvariable"
In this case, read will split the (first line of the) expansion of the variable keyvariable on the spaces, but only for the first and second fields (these will go in variables a and b) and the remaining part will go in c. The -r switch is used in case you have backslashes in your string; without this, backslashes would be treated as an escape character.
gniourf_gniourf's answer is absolutely correct, however if you don't know how many fields you are going to have or need to select your "prefix" fields based on some other criteria then using an array and Substring Expansion (which is a bad name for this usage of it but that's what it is called) can let you do that.
$ keyvariable="aa bb cc dd ee ff"
$ read -a line <<<"$keyvariable"
$ a=${line[0]}
$ b=${line[1]}
$ c=${line[#]:2}
$ echo "$a"
aa
$ echo "$b"
bb
$ echo "$c"
cc dd ee ff
Also note the lack of $(echo ...) on the assignment lines. You don't need it.
Just do
a=( $keyvariable )
and you have array a with your values, so your example would be
keyvariable="aa bb cc dd ee ff"
line=( $keyvariable ) # of course you can do it in the same line
a="${line[0]}"
b="${line[1]}"
n=$(( ${#line[#]} - 1))
unset line[$n]
echo "$a $b $c"