awk : how to use variable value - linux

I want to declare a variable called variableToUse which holds the file name path.
I want to append file name with today's date.
Below code is in myAWK.awk
$bash: cat myAWK.awk
BEGIN{
today="date +%Y%m%d";
variableToUse=/MainDir/MainDir1/MainDir2/OutputFile_today.xml
}
/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
if (found) {
print a[i] >> variableToUse
}
}
I am getting syntax error at OutputFile_today.xml.
How to use variable value?

You should quote the variables properly
Example
$ awk 'BEGIN{variableToUse="/MainDir/MainDir1/MainDir2/OutputFile_today.xml"; print variableToUse}'
/MainDir/MainDir1/MainDir2/OutputFile_today.xml
To get the current date you can use strftime
Example
$ awk 'BEGIN{today="date +%Y%m%d";variableToUse="/MainDir/MainDir1/MainDir2/OutputFile_"strftime("%Y%m%d")".xml"; print variableToUse}'
/MainDir/MainDir1/MainDir2/OutputFile_20160205.xml

Have your awk script like this:
BEGIN {
today="date +%Y%m%d";
variableToUse="/MainDir/MainDir1/MainDir2/OutputFile_" today ".xml"
}
/<record / { i=1 }
i { a[i++]=$0 }
/<\/record>/ {
if (found) {
print a[i] >> variableToUse
}
}
btw there are couple of other issues:
- I don't see found getting set anywhere in this script.
- today="date +%Y%m%d" will not execute date command. It just assigns literaldate +%Y%m%dtotodayvariable. If you want to executedate` command then use:
awk -v today="$(date '+%Y%m%d')" -f myAWK.awk
and remove today= line from BEGIN block.

Related

How to read function names from file and prefix file with said function names in Bash effectively?

I have a bunch of files which I concatenate into one large file. The single large file then looks like this:
function foo() {
// ... implementation
}
function bar() {
// ... implementation
}
function baz() {
// ... implementation
}
function foo_bar() {
// ... implementation
}
...
A bunch of functions. I want to create a new file with all this content, PLUS prefixing it with this:
module.exports = {
foo,
bar,
baz,
foo_bar,
...
}
Basically exporting every function. What is the most simple, cleanest way I can do this in bash?
As far as I got is this haha, it is really confusing to try and come up with a solution:
A := out/a.js
B := out/b.js
all: $(A) $(B)
$(A):
#find src -name '*.js' -exec cat {} + > $#
$(B):
#cat out/a.js | grep -oP '(?function )[a-zA-Z0-9_]+(? \{)'
.PHONY: all
Store the list of functions declared before and after sourcing the file. Compute the difference. You can get the list of currently declared functions with declare -F.
A() { :; }
pre=$(declare -F | sed 's/^declare -f //')
function foo() {
// ... implementation
}
function bar() {
// ... implementation
}
function baz() {
// ... implementation
}
function foo_bar() {
// ... implementation
}
post=$(declare -F | sed 's/^declare -f //')
diff=$(comm -13 <(sort <<<"$pre") <(sort <<<"$post"))
echo "module.exports = {
$(<<<"$diff" paste -sd, | sed 's/,/,\n\t/g')
}"
I think with bash --norc you should get a clean environment, so with bash --norc -c 'source yourfile.txt; declare -F' you could get away with computing the difference:
cat <<EOF >yourfile.txt
function foo() {
// ... implementation
}
function bar() {
// ... implementation
}
function baz() {
// ... implementation
}
function foo_bar() {
// ... implementation
}
EOF
diff=$(bash --norc -c 'source yourfile.txt; declare -F' | cut -d' ' -f3-)
echo "module.exports = {
$(<<<"$diff" paste -sd, | sed 's/,/,\n\t/g')
}"
Both code snippets should output:
module.exports = {
bar,
baz,
foo,
foo_bar
}
Note: the function name() {} is a mix of ksh and posix form of function definition - the ksh uses function name {} while posix uses name() {}. Bash supports both forms and also the strange mix of both forms. To be portable, just use the posix version name() {}. More info maybe at wiki-deb-bash-hackers.org obsolete and deprecated syntax.
This simple awk script will do it
awk -F '( |\\()' 'BEGIN {print "module.exports = {"} /function/ {print "\t" $2 ","} END {print "}"}' largefile.js
You could use echo and sed:
echo 'modules.exports = {'; sed -n 's/^function \([^(]*\)(.*/ \1,/p' input.txt; echo '}'
result:
modules.exports = {
foo,
bar,
baz,
foo_bar,
}

How to take the data between two strings in a file Linux

I want to get the lines between forwarders { and }; those are IP address, below is the sample file which mimics my data..
// Red Hat BIND Configuration Tool
//
// THIS IS THE SLAVE DDNS SERVER -
//
// Currently running in chroot environment
// Prefix all file names below with /var/named/chroot
options {
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
recursion yes;
check-names master ignore;
check-names slave ignore;
check-names respocope ignore;
max-journal-size 2M;
allow-query { any; };
allow-update {
key copdcop1.example.com.;
key copdcop2.example.com.;
key copdcop3.example.com.;
key copdcop4.example.com.;
};
forward only;
forwarders {
192.168.174.131; // cop-no1
192.155.98.74; // cop-jn1
192.168.2.40; // cop-sad1
192.168.2.56; // cop-s1
192.43.4.70; // cop-che1
192.20.28.8; // copdcop1
};
Desired Result:
192.168.174.131; // cop-no1
192.155.98.74; // cop-jn1
192.168.2.40; // cop-sad1
192.168.2.56; // cop-s1
192.43.4.70; // cop-che1
192.20.28.8; // copdcop1
I'm okay with any solution either shell or python or awk.
I tried with sed but no luck..
sed -n '"/forwarders {"/,/"};"' dns.txt
However, below awk code works ..
awk '/forwarders {/{flag=1;next}/};/{flag=0}flag' dns.txt
sed -n '/forwarders {/,/};/{//!p}' file
Given your sample its output:
192.168.174.131; // cop-no1
192.155.98.74; // cop-jn1
192.168.2.40; // cop-sad1
192.168.2.56; // cop-s1
192.43.4.70; // cop-che1
1192.20.28.8; // copdcop1
It really depends in how much the file can change.
But this would work for your example:
awk '/forwarders {/{flag=1;next}/};/{flag=0}flag' /path/to/file
For your example:
192.168.174.131; // cop-no1
192.155.98.74; // cop-jn1
192.168.2.40; // cop-sad1
192.168.2.56; // cop-s1
192.43.4.70; // cop-che1
192.20.28.8; // copdcop1
EDIT: Since OP asked to have output into single line so adding following solution now.
awk 'BEGIN{OFS=","} /}/{found=""} /forwarders {/{found=1} found && match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/){gsub(/ +/," ");val=(val?val OFS:"")$0}END{print val}' Input_file
OR non-one liner form of solution.
awk '
BEGIN{
OFS=","
}
/}/{
found=""
}
/forwarders {/{
found=1
}
found && match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/){
gsub(/ +/," ")
val=(val?val OFS:"")$0
}
END{
print val
}' Input_file
OR as mentioned before too, to print anything inside forwarder block try:
awk '/}/{found=""} /forwarders {/{found=1;next} found{gsub(/ +/," ");val=(val?val OFS:"")$0} END{print val}' Input_file
Could you please try following(considering that you only need to print IP addresses inside the tag).
awk '/}/{found=""} /forwarders {/{found=1} found && match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)' Input_file
In case forwarders tag you want to anything then try following.
awk '/}/{found=""} /forwarders {/{found=1;next} found' Input_file

how to call a function within another variable which has backtick in Shell Script

I want to call a function within another variable which has back-tick. how do i make this work?
example:
location ()
{echo "home/$1/dir"}
count_files ()
{
count=`ls $(location user1) |wc -l`
}
count_files
You can use this :
location() {
echo "home/$1/dir"
}
count_files() {
count=$(ls $(location user1) | wc -l)
}
count_files
You must set the correct execution syntax.
$(Command)
or with back-ticks
`Command`
In your example you missing that bevor the ls ... command. And you missing the first slash in your home Directory (Otherwise, it would only work from root / Directory.)
Try:
#!/bin/bash
location () {
echo "/home/$1/dir"
}
count_files () {
# Get the count;
count=$(ls $(location "$1") | wc -l);
# Return the count value;
echo "$count";
}
# Call function and print the count result.
# Better you set the user here and not 'hardcoded' in a function.
echo $(count_files "user1")

Awk in loopwith different file

I have four files and want to run a awk code on each file. But this code is not working.
My code:
for i in "udp-250b.tr" "udp-50b.tr"
do
awk '
BEGIN {
//some code
}
{
//some code
}
END {
//some code
} ' i
done
Awk can work with multiple files no need of for
syntax will be like this
awk '{ }' file1 file2 file3
or
awk '{ }' file*
In your case
awk 'BEGIN{ } { } END{ }' udp-*.tr
To correct your existing code change
} ' i
To
} ' "$i"

String read in from file not responding to string manipulation

I have a Perl subroutine that creates a file, like so:
sub createFile {
if (open (OUTFILEHANDLE, ">$fileName")) {
print OUTFILEHANDLE "$desiredVariable\n";
}
close(OUTFILEHANDLE);
}
where $fileName and $desiredVariable have been previously defined. I call that, and then call the following subroutine, which reads from the file, takes the first (only) line, and saves it into the variable $desiredVariable:
sub getInfoFromFile {
if (existFile($fileName)) {
if (open (READFILEHANDLE, "<$fileName")) {
my #entire_file=<READFILEHANDLE>; # Slurp
$desiredVariable = $entire_file[0];
chop $desiredVariable;
close(READFILEHANDLE);
}
}
}
If I leave out the "chop" line, $desiredVariable is what I want, but with a trailing space newline. If I include the "chop" line, $desiredVariable is an empty string. For some reason, "chop" is killing the whole string. I've tried it with $desiredVariable =~ s/\s*$//; and several other string manipulation tricks.
What am I doing wrong?
The code you included does not reproduce the problem. I'm guessing it was lost in translation somehow while you were anonymizing it. I ran the script as follows, the only adjustment I made was -f instead of existsFile().
#!/usr/bin/perl
sub createFile {
if (open (OUTFILEHANDLE, ">$fileName")) {
print OUTFILEHANDLE "$desiredVariable\n";
}
close(OUTFILEHANDLE);
}
sub getInfoFromFile {
if (-f $fileName) {
if (open (READFILEHANDLE, "<$fileName")) {
my #entire_file=<READFILEHANDLE>; # Slurp
$desiredVariable = $entire_file[0];
chop $desiredVariable;
close(READFILEHANDLE);
}
}
}
$fileName = "test.txt";
$desiredVariable = "Hello World!";
createFile();
$desiredVariable = "";
getInfoFromFile();
print "Got '$desiredVariable'\n"; # Got 'Hello World!'

Resources