I'm doing a script to parse m3u files.
The goal is to retrieve the variable tag and the url.
I tested with this file.
#!/bin/bash
echo "name,tvg-id,tvg-name,tvg-country,group-title,languages,url"
while IFS= read -r line; do
tags_detect="$(echo "$line" | grep -Eo '^#EXTINF:')"
if [[ -n ${tag_detect} ]]; then
get_chno="$(echo "$line" | grep -o 'tvg-chno="[^"]*' | cut -d '"' -f2)"
get_id="$(echo "$line" | grep -o 'tvg-id="[^"]*' | cut -d '"' -f2)"
get_logo="$(echo "$line" | grep -o 'tvg-logo="[^"]*' | cut -d '"' -f2)"
get_grp_title="$(echo "$line" | grep -o 'group-title="[^"]*' | cut -d '"' -f2)"
get_title="$(echo "$line" | grep -o ',[^*]*' | cut -d ',' -f2)"
get_tvg_name="$(echo "$line" | grep -o 'tvg-name="[^"]*' | cut -d '"' -f2)"
get_country="$(echo "$line" | grep -o 'tvg-country="[^"]*' | cut -d '"' -f2)"
get_language="$(echo "$line" | grep -o 'tvg-language="[^"]*' | cut -d '"' -f2)"
phrase="${get_title},${get_id},${get_tvg_name},${get_country},${get_grp_title},${get_language}"
else
url="$line"
fi
echo "${phrase},${url}"
done <"${1}"
So, Without "If" it works but i don't have url.
I add a "IF" and ... :
,#EXTM3U
4 Turk Music,4TurkMusic.fr,4 Turk Music,FR;TK,Music,Turkish,#EXTM3U
4 Turk Music,4TurkMusic.fr,4 Turk Music,FR;TK,Music,Turkish,http://51.210.199.30/hls/stream.m3u8
Alpe d’Huez TV,AlpedHuezTV.fr,Alpe d’Huez TV,FR,,French,http://51.210.199.30/hls/stream.m3u8
Alpe d’Huez TV,AlpedHuezTV.fr,Alpe d’Huez TV,FR,,French,https://edge10.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8
... It's broken and I don't found my error.
desired output:
4 Turk Music,4TurkMusic.fr,4 Turk Music,FR;TK,Music,Turkish,http://1.2.3.4/hls/stream.m3u8
Alpe d’Huez TV,AlpedHuezTV.fr,Alpe d’Huez TV,FR,,French,https://edge10.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8
I don't understand my mistake.
It's broken and I don't found my error.
Paste you script at https://shellcheck.net for validation/recommendation.
Here is how I would do it in bash.
#!/usr/bin/env bash
printf '%s\n' "name,tvg-id,tvg-name,tvg-country,group-title,languages,url"
while IFS= read -r data; do
[[ $data != '#EXTINF:-1'* ]] && continue
IFS= read -r url && [[ $url != 'http'* ]] && echo "$url" && continue
if [[ "$data" == '#EXTINF:-1'* && "$url" == 'http'* ]]; then
title=${data#*\",}
tvg_id=${data#*tvg-id=\"} tvg_id=${tvg_id%%\"*}
tvg_name=${data#*tvg-name=\"} tvg_name=${tvg_name%%\"*}
tvg_country=${data#*tvg-country=\"} tvg_country=${tvg_country%%\"*}
group_title=${data#*group-title=\"} group_title=${group_title%%\",*}
tvg_language=${data#*tvg-language=\"} tvg_language=${tvg_language%%\"*}
printf '%s,%s,%s,%s,%s,%s,%s\n' "$title" "$tvg_id" "$tvg_name" "$tvg_country" "$group_title" "$tvg_language" "$url"
fi
done < file.txt
Although I'm not sure what should happen at line 233 and 238 those lines starts with #EXTVLCOPT
An ed solution if available/acceptable.
The script, name it anything you like. I'll just name it script.ed
g/^#EXTINF:-1/s/$/ /\
;/^http\(s\)\{0,1\}.*/-1;/^[^#]*$/j
,s/^#EXTINF:-1 tvg-id="\([^"]*\)" tvg-name="\([^"]*\)" tvg-country="\([^"]*\)" tvg-language="\([^"]*\).* group-title="\([^"]*\)",\(.*\) \(http.*\)\{0,1\}/\6,\1,\2,\3,\5,\4,\7/
1c
name,tvg-id,tvg-name,tvg-country,group-title,languages,url
.
,p
Q
Now run it against the file in question.
ed -s file.txt < script.ed
Remove the ,p from the script to silence the output to stdout or if you're satisfied with the output.
Change Q to w from the script if in-place editing is needed.
Should give more or less same result as the bash solution, but since it is still unknown what should happen at line 233 and 238 those lines starts with #EXTVLCOPT
You probably better use a more capable language like Perl.
#! /usr/bin/perl
use strict;
use warnings;
print "name,tvg-id,tvg-name,tvg-country,group-title,languages,url\n";
my %tags;
my $title;
while (<>)
{
next if /^#EXTM3U/;
if (s/^#EXTINF:-1//) {
%tags = ();
$tags{$1} = $2 while (s/\s*(\S+)="([^"]*)"//);
($title) = $_ =~ /,(.*)/;
} else {
print join (',', $title,
$tags{'tvg-id'},
$tags{'tvg-name'},
$tags{'tvg-country'},
$tags{'group-title'},
$tags{'tvg-language'},
$_);
}
}
A quick refactor (untested) -
declare -A tag
while IFS= read -r line; do
case "$line" in
\#EXTINF:*)
if [[ "$line" =~ ,([^*]+) && -n "${BASH_REMATCH[0]}" ]]; then
tag[title]="${BASH_REMATCH[0]}"
phrase="${tag[title]}"
fi
for id in tvg-id tvg-name tvg-country group-title tvg-language tvg-chno tvg-logo; do
pat=$id'="([^"]+)"'
[[ "$line" =~ $pat ]] && tag[$id]="${BASH_REMATCH[0]}";
phrase="$phrase,${tag[$id]}"
done
phrase="${phrase%,${tag[tvg-chno]},${tag[tvg-logo]}}"
;;
*) url="$line"
esac
echo "${phrase},${url}"
done <"${1}"
Needs a lot more error checking...
I have a Property file in Jenkins lets call it Something.txt
and Something.txt contains
A_B_C
D_E_F
and i have used below shell to read the file and Execute my Automation
file="/var/lib/jenkins/components.txt"
if [ -f "$file" ]
then
echo "$file found."
Websites="$(awk -F '_' '{print $1}' $file | paste -d, -s)"
Profiles="$(awk -F '_' '{print $2}' $file | paste -d, -s)"
Component="$(awk -F '_' '{print $3}' $file | paste -d, -s)"
for i in $(echo $Websites | sed "s/,/ /g"); do
for j in $(echo $Profiles | sed "s/,/ /g"); do
for k in $(echo $Component| sed "s/,/ /g"); do
mvn clean verify -D "cucumber.options=--tags #"${j} -D surefire.suiteXmlFiles=./XMLScripts/${i}.${k}.testng.xml ||true
done
done
done
but what is happening is My Job is running as
A-B-C & A-B-F & D-B-C & B-E-F
but the expected result is A-B-C & D-E-F how to achieve this?
Don't read lines with for
#!/usr/bin/env bash
file="/var/lib/jenkins/components.txt"
if [[ -f "$file" ]]; then
while IFS=_ read -r website profile component; do
printf '%s %s %s\n' "$website" "$profile" "$component"
done < "$file"
fi
In your case you can do
#!/usr/bin/env bash
file="/var/lib/jenkins/components.txt"
if [[ -f "$file" ]]; then
while IFS=_ read -r website profile component; do
echo mvn clean verify -D cucumber.options=--tags #"$website" -D "surefire.suiteXmlFiles=./XMLScripts/$profile.$component.testng.xml" ||true
done < "$file"
fi
Remove the echo if you're satisfied with the result.
My aim is to transform the output (the last 2 lines) of the ping command in a CSV style.
Here are some examples:
In case there is a packet loss lower than 100% <
URL, PacketLoss, Min, Average, Max, Deviation
In case there is packet loss equal to 100%
URL, 100, -1, -1, -1, -1
My script is below, but when the packet loss is 100% the output is:
URL, 100,
So the problem is at the if statement, as it does not enter in elif, I use the same syntax as checking if the address is full or not (with "www." or not).
Can you please have a look because I tried multiple things and it did not work.
My script:
#!/bin/bash
declare site=''
declare result='';
if [[ "$1" == "www."* ]]; then
site="$1";
else
site="www.$1";
fi
result="$site";
pingOutput=$(ping $site -c10 -i0.2 -q| tail -n2);
fl=true;
while IFS= read -r line
do
# !!! The problem is here, the if statement is not working properly and I do not know why !!!
if [ "$fl" == "true" ]; then
result="$result $(echo "$line" | cut -d',' -f3 | cut -d" " -f2 | sed -r 's/%//g')";
fl=false;
elif [[ "$line" == "ms"* ]]; then
result="$result $(echo "$line" | cut -d' ' -f4 | sed -r 's/\// /g')";
else
result="$result -1 -1 -1 -1";
fi
done <<< "$pingOutput"
echo "$result";
This is a pretty old question but I've just stumbled upon it today. Below I paste a slight modified version of the above script that fixes the if issue and works on Mac OS.
P.S. You can uncomment the # prctg=100.0% line to see the if working.
#!/bin/bash
declare site=''
declare result=''
declare prctg=''
[[ "$1" == "www."* ]] && site="$1" || site="www.$1"
result="$site"
pingOutput=$(ping $site -c10 -i0.2 -q | tail -n2)
fl=true
while IFS= read -r line
do
#echo $line
if [ "$fl" == "true" ]
then
prctg=$(echo "$line" | grep -Eo "[.[:digit:]]{1,10}%")
result="$result,$prctg"
fl=false
# prctg=100.0%
else
if [ "$prctg" == "100.0%" ]
then
result="$result,-1,-1,-1,-1"
else
result="$result,$(echo "$line" | cut -d' ' -f4 | sed -E 's/\//,/g')"
fi
fi
done <<< "$pingOutput"
echo "$result"
I hope it helps someone from the future! :)
Since the second line of the pingOutput was never processed (the loop ended before) the action of adding the -1 to the output was never performed.
Due to this problem I decided to capture the percentage of failure and act when no packets were returned (100%), I also simplified some expressions you used initially.
I investigated the script and came up with the following solution:
#!/bin/bash
declare site=''
declare result=''
declare prctg=''
[[ "$1" == "www."* ]] && site="$1" || site="www.$1"
result="$site"
pingOutput=$(ping $site -c10 -i0.2 -q| tail -n2)
fl=true
while IFS= read -r line
do
# !!! The problem is here, the if statement is not working properly and I do not know why !!!
echo $line
if [ "$fl" == "true" ]
then
prctg=$(echo "$line" | grep -Po "[0-9]{0,3}(?=%)")
result="$result $prctg"
fl=false
fi
if [ "$prctg" == "100" ]
then
result="$result -1 -1 -1 -1"
else
result="$result $(echo "$line" | cut -d' ' -f4 | sed -r 's/\// /g')"
fi
done <<< "$pingOutput"
echo "$result"
I'm trying to make a simple bash script that will iterate through a text file containing IP addresses,
ping them one time, and see if they are alive or not.
This is my work so far:
#!/bin/bash
for ip in $(cat ips.txt); do
if [[ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)"]]
echo $ip
fi
done
Any Suggestions?
Thanks!
This seems to work:
#!/bin/bash
for ip in $(cat ips.txt); do
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]; then
echo $ip
fi
done
You needed the ; then after the if [ ... ] statement (same thing goes for elif, not else), and a space between the last bracket of the statement and the statement's contents. Also this appears to work fine with just single brackets, and this may be more portable (see here).
Works on Bash 4.2.47
Yes. You can use a newline instead of ; if you like, but you always need the then keyword.
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]
then echo $ip
fi
# or
if [ "1" == "$(ping -c 1 $ip | grep 'packets transmitted' | cut -d ' ' -f 4)" ]
then
echo $ip
fi
I'm looking for the easiest and most readable way to remove a field from a path. So for example, I have /this/is/my/complicated/path/here, and I would like to remove the 5th field ("/complicated") from the string, using bash commands, so that it becomes /this/is/my/path.
I could do this with
echo "/this/is/my/complicated/path/here" | cut -d/ -f-4
echo "/"
echo "/this/is/my/complicated/path/here" | cut -d/ -f6-
but I would like this done in just one easy command, something that would like
echo "/this/is/my/complicated/path" | tee >(cut -d/ -f-4) >(cut -d/ -f6-)
except that this doesn't work.
With cut, you can specify a comma separated list of fields to print:
$ echo "/this/is/my/complicated/path/here" | cut -d/ -f-4,6-
/this/is/my/path/here
So, it's not really necessary to use two commands.
How about using sed?
$ echo "/this/is/my/complicated/path/here" | sed -e "s%complicated/%%"
/this/is/my/path/here
This removes the 5th path element
echo "/this/is/my/complicated/path/here" |
perl -F/ -lane 'splice #F,4,1; print join("/", #F)'
just bash
IFS=/ read -a dirs <<< "/this/is/my/complicated/path/here"
newpath=$(IFS=/; echo "${dirs[*]:0:4} ${dirs[*]:5}")
Anything wrong with a bash script?
#!/bin/bash
if [ -z "$1" ]; then
us=$(echo $0 | sed "s/^\.\///") # Get rid of a starting ./
echo " "Usage: $us StringToParse [delimiterChar] [start] [end]
echo StringToParse: string to remove something from. Required
echo delimiterChar: Character to mark the columns "(default '/')"
echo " "start: starting column to cut "(default 5)"
echo " "end: last column to cut "(default 5)"
exit
fi
# Parse the parameters
theString=$1
if [ -z "$2" ]; then
delim=/
start=4
end=6
else
delim=$2
if [ -z "$3" ]; then
start=4
end=6
else
start=`expr $3 - 1`
if [ -z "$4" ]; then
end=6
else
end=`expr $4 + 1`
fi
fi
fi
result=`echo $theString | cut -d$delim -f-$start`
result=$result$delim
final=`echo $theString | cut -d$delim -f$end-`
result=$result$final
echo $result