Here's my PS1 variable:
PS1='\u:\W$(__git_ps1 "\e[32m\][%s]\e[0m\]")$ '
Works great for picking up my Git branch, but it has the unfortunate side-effect of wrapping the lines when the colours are active, so that they overlap when you use long commands.
Can anyone with magic PS1 skills help me out to fix this?
Got it, needed to escape the colours properly.
Fix:
PS1='\u:\W$(__git_ps1 "\[\e[32m\][%s]\[\e[0m\]")$ '
May I suggest the following method for colors in Bash, it makes the code much more readable and alot harder for you to miss an escape or two.
Put the following in your ~/.bashrc
BLACK=$(tput setaf 0)
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
LIME_YELLOW=$(tput setaf 190)
YELLOW=$(tput setaf 3)
POWDER_BLUE=$(tput setaf 153)
BLUE=$(tput setaf 4)
MAGENTA=$(tput setaf 5)
CYAN=$(tput setaf 6)
WHITE=$(tput setaf 7)
BRIGHT=$(tput bold)
NORMAL=$(tput sgr0)
BLINK=$(tput blink)
REVERSE=$(tput smso)
UNDERLINE=$(tput smul)
A sample PS1 (or really anything that prints to the screen) would be:
PS1="\[${WHITE}\](\[${YELLOW}\]\u#\h\[${WHITE}\])\[${NORMAL}\]$ "
You need only put \[ \] around the color words.
If you have a 256-color terminal, you can experiment with other numerical values to 'tput setaf' all the way up to 255.
These are the color functions I use regularly... wrote them years ago and have gotten so used to them that they're a regular part of my scripting. Just stick this code block into your .bashrc file, start a new session, and you're set!
I use these as colorful/stylish printf replacements:
## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ [ Aesthir's Color Functions ] ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
Normal () { printf '\e[m'"$*"; } ; Tblack () { printf '\e[0;30m'"$*"'\e[m'; }
TNormal () { printf '\e[m'"$*"; } ; Tred () { printf '\e[0;31m'"$*"'\e[m'; }
Bold () { printf '\e[1m'"$*"'\e[m'; } ; Tgreen () { printf '\e[0;32m'"$*"'\e[m'; }
TBold () { printf '\e[1m'"$*"'\e[m'; } ; Tbrown () { printf '\e[0;33m'"$*"'\e[m'; }
Underline () { printf '\e[4m'"$*"'\e[m'; } ; Tyellow () { printf '\e[0;33m'"$*"'\e[m'; }
TUnderline () { printf '\e[4m'"$*"'\e[m'; } ; Tblue () { printf '\e[0;34m'"$*"'\e[m'; }
Flash () { printf '\e[5m'"$*"'\e[m'; } ; Tmagenta () { printf '\e[0;35m'"$*"'\e[m'; }
TFlash () { printf '\e[5m'"$*"'\e[m'; } ; Tpurple () { printf '\e[0;35m'"$*"'\e[m'; }
Invert () { printf '\e[7m'"$*"'\e[m'; } ; Taqua () { printf '\e[0;36m'"$*"'\e[m'; }
TInvert () { printf '\e[7m'"$*"'\e[m'; } ; Tcyan () { printf '\e[0;36m'"$*"'\e[m'; }
Invisible () { printf '\e[8m'"$*"'\e[m'; } ; Tgrey () { printf '\e[0;37m'"$*"'\e[m'; }
TInvisible () { printf '\e[8m'"$*"'\e[m'; } ; Twhite () { printf '\e[0;37m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ Bold Color Text ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ## ∞∞∞∞∞∞∞∞∞∞∞∞ Underlined Color Text ∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
TblackB () { printf '\e[1;30m'"$*"'\e[m'; } ; TblackU () { printf '\e[4;30m'"$*"'\e[m'; }
TgreyB () { printf '\e[1;30m'"$*"'\e[m'; } ; TredU () { printf '\e[4;31m'"$*"'\e[m'; }
TredB () { printf '\e[1;31m'"$*"'\e[m'; } ; TgreenU () { printf '\e[4;32m'"$*"'\e[m'; }
TgreenB () { printf '\e[1;32m'"$*"'\e[m'; } ; TbrownU () { printf '\e[4;33m'"$*"'\e[m'; }
TbrownB () { printf '\e[1;33m'"$*"'\e[m'; } ; TyellowU () { printf '\e[4;33m'"$*"'\e[m'; }
TyellowB () { printf '\e[1;33m'"$*"'\e[m'; } ; TblueU () { printf '\e[4;34m'"$*"'\e[m'; }
TblueB () { printf '\e[1;34m'"$*"'\e[m'; } ; TmagentaU () { printf '\e[4;35m'"$*"'\e[m'; }
TmagentaB () { printf '\e[1;35m'"$*"'\e[m'; } ; TpurpleU () { printf '\e[4;35m'"$*"'\e[m'; }
TpurpleB () { printf '\e[1;35m'"$*"'\e[m'; } ; TaquaU () { printf '\e[4;36m'"$*"'\e[m'; }
TaquaB () { printf '\e[1;36m'"$*"'\e[m'; } ; TcyanU () { printf '\e[4;36m'"$*"'\e[m'; }
TcyanB () { printf '\e[1;36m'"$*"'\e[m'; } ; TgreyU () { printf '\e[4;37m'"$*"'\e[m'; }
TwhiteB () { printf '\e[1;37m'"$*"'\e[m'; } ; TwhiteU () { printf '\e[4;37m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞∞∞∞∞∞∞ Flashing Color Text ∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ## ∞∞∞∞∞∞∞∞∞∞∞∞∞ Inverted Color Text ∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
TblackF () { printf '\e[5;30m'"$*"'\e[m'; } ; TblackI () { printf '\e[7;40m'"$*"'\e[m'; }
TredF () { printf '\e[5;31m'"$*"'\e[m'; } ; TredI () { printf '\e[7;41m'"$*"'\e[m'; }
TgreenF () { printf '\e[5;32m'"$*"'\e[m'; } ; TgreenI () { printf '\e[7;42m'"$*"'\e[m'; }
TbrownF () { printf '\e[5;33m'"$*"'\e[m'; } ; TbrownI () { printf '\e[7;43m'"$*"'\e[m'; }
TyellowF () { printf '\e[5;33m'"$*"'\e[m'; } ; TyellowI () { printf '\e[7;43m'"$*"'\e[m'; }
TblueF () { printf '\e[5;34m'"$*"'\e[m'; } ; TblueI () { printf '\e[7;44m'"$*"'\e[m'; }
TmagentaF () { printf '\e[5;35m'"$*"'\e[m'; } ; TmagentaI () { printf '\e[7;45m'"$*"'\e[m'; }
TpurpleF () { printf '\e[5;35m'"$*"'\e[m'; } ; TpurpleI () { printf '\e[7;45m'"$*"'\e[m'; }
TaquaF () { printf '\e[5;36m'"$*"'\e[m'; } ; TaquaI () { printf '\e[7;46m'"$*"'\e[m'; }
TcyanF () { printf '\e[5;36m'"$*"'\e[m'; } ; TcyanI () { printf '\e[7;46m'"$*"'\e[m'; }
TgreyF () { printf '\e[5;37m'"$*"'\e[m'; } ; TgreyI () { printf '\e[7;47m'"$*"'\e[m'; }
TwhiteF () { printf '\e[5;37m'"$*"'\e[m'; } ; TwhiteI () { printf '\e[7;47m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞∞∞∞∞∞∞ Invisible Color Text ∞∞∞∞∞∞∞∞∞∞∞∞∞ ## ∞∞∞∞∞∞∞∞ Plain Text on Color Background ∞∞∞∞∞∞∞∞ ##
TblackV () { printf '\e[8;30m'"$*"'\e[m'; } ; Bblack () { printf '\e[m'"$*"'\e[m'; }
TredV () { printf '\e[8;31m'"$*"'\e[m'; } ; Bred () { printf '\e[0;41m'"$*"'\e[m'; }
TgreenV () { printf '\e[8;32m'"$*"'\e[m'; } ; Bgreen () { printf '\e[0;42m'"$*"'\e[m'; }
TbrownV () { printf '\e[8;33m'"$*"'\e[m'; } ; Bbrown () { printf '\e[0;43m'"$*"'\e[m'; }
TyellowV () { printf '\e[8;33m'"$*"'\e[m'; } ; Byellow () { printf '\e[0;43m'"$*"'\e[m'; }
TblueV () { printf '\e[8;34m'"$*"'\e[m'; } ; Bblue () { printf '\e[0;44m'"$*"'\e[m'; }
TmagentaV () { printf '\e[8;35m'"$*"'\e[m'; } ; Bmagenta () { printf '\e[0;45m'"$*"'\e[m'; }
TpurpleV () { printf '\e[8;35m'"$*"'\e[m'; } ; Bpurple () { printf '\e[0;45m'"$*"'\e[m'; }
TaquaV () { printf '\e[8;36m'"$*"'\e[m'; } ; Baqua () { printf '\e[0;46m'"$*"'\e[m'; }
TcyanV () { printf '\e[8;36m'"$*"'\e[m'; } ; Bcyan () { printf '\e[0;46m'"$*"'\e[m'; }
TgreyV () { printf '\e[8;37m'"$*"'\e[m'; } ; Bgrey () { printf '\e[0;47m'"$*"'\e[m'; }
TwhiteV () { printf '\e[8;37m'"$*"'\e[m'; } ; Bwhite () { printf '\e[0;47m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞∞∞ Bold Text on Color Background ∞∞∞∞∞∞∞∞ ## ∞∞∞∞∞∞ Underlined Text on Color Background ∞∞∞∞∞ ##
BblackB () { printf '\e[1;40m'"$*"'\e[m'; } ; BblackU () { printf '\e[4;40m'"$*"'\e[m'; }
BredB () { printf '\e[1;41m'"$*"'\e[m'; } ; BredU () { printf '\e[4;41m'"$*"'\e[m'; }
BgreenB () { printf '\e[1;42m'"$*"'\e[m'; } ; BgreenU () { printf '\e[4;42m'"$*"'\e[m'; }
BbrownB () { printf '\e[1;43m'"$*"'\e[m'; } ; BbrownU () { printf '\e[4;43m'"$*"'\e[m'; }
ByellowB () { printf '\e[1;43m'"$*"'\e[m'; } ; ByellowU () { printf '\e[4;43m'"$*"'\e[m'; }
BblueB () { printf '\e[1;44m'"$*"'\e[m'; } ; BblueU () { printf '\e[4;44m'"$*"'\e[m'; }
BmagentaB () { printf '\e[1;45m'"$*"'\e[m'; } ; BmagentaU () { printf '\e[4;45m'"$*"'\e[m'; }
BpurpleB () { printf '\e[1;45m'"$*"'\e[m'; } ; BpurpleU () { printf '\e[4;45m'"$*"'\e[m'; }
BaquaB () { printf '\e[1;46m'"$*"'\e[m'; } ; BaquaU () { printf '\e[4;46m'"$*"'\e[m'; }
BcyanB () { printf '\e[1;46m'"$*"'\e[m'; } ; BcyanU () { printf '\e[4;46m'"$*"'\e[m'; }
BgreyB () { printf '\e[1;47m'"$*"'\e[m'; } ; BgreyU () { printf '\e[4;47m'"$*"'\e[m'; }
BwhiteB () { printf '\e[1;47m'"$*"'\e[m'; } ; BwhiteU () { printf '\e[4;47m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞ Flashing Text on Color Background ∞∞∞∞∞∞ ## ∞∞∞∞∞∞∞ Inverted Text on Color Background ∞∞∞∞∞∞ ##
BblackF () { printf '\e[5;40m'"$*"'\e[m'; } ; BblackI () { printf '\e[7;30m'"$*"'\e[m'; }
BredF () { printf '\e[5;41m'"$*"'\e[m'; } ; BredI () { printf '\e[7;31m'"$*"'\e[m'; }
BgreenF () { printf '\e[5;42m'"$*"'\e[m'; } ; BgreenI () { printf '\e[7;32m'"$*"'\e[m'; }
BbrownF () { printf '\e[5;43m'"$*"'\e[m'; } ; BbrownI () { printf '\e[7;33m'"$*"'\e[m'; }
ByellowF () { printf '\e[5;43m'"$*"'\e[m'; } ; ByellowI () { printf '\e[7;33m'"$*"'\e[m'; }
BblueF () { printf '\e[5;44m'"$*"'\e[m'; } ; BblueI () { printf '\e[7;34m'"$*"'\e[m'; }
BmagentaF () { printf '\e[5;45m'"$*"'\e[m'; } ; BmagentaI () { printf '\e[7;35m'"$*"'\e[m'; }
BpurpleF () { printf '\e[5;45m'"$*"'\e[m'; } ; BpurpleI () { printf '\e[7;35m'"$*"'\e[m'; }
BaquaF () { printf '\e[5;46m'"$*"'\e[m'; } ; BaquaI () { printf '\e[7;36m'"$*"'\e[m'; }
BcyanF () { printf '\e[5;46m'"$*"'\e[m'; } ; BcyanI () { printf '\e[7;36m'"$*"'\e[m'; }
BgreyF () { printf '\e[5;47m'"$*"'\e[m'; } ; BgreyI () { printf '\e[7;37m'"$*"'\e[m'; }
BwhiteF () { printf '\e[5;47m'"$*"'\e[m'; } ; BwhiteI () { printf '\e[7;37m'"$*"'\e[m'; }
## ∞∞∞∞∞∞ Invisible Text on Color Background ∞∞∞∞∞∞ ## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ Color Code Notes ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
BblackV () { printf '\e[8;40m'"$*"'\e[m'; } ## Unless I missed something or made a mistake, I ##
BredV () { printf '\e[8;41m'"$*"'\e[m'; } ## calculate a total of 7681 different color codes, ##
BgreenV () { printf '\e[8;42m'"$*"'\e[m'; } ## none of which produce a duplicate result. ##
BbrownV () { printf '\e[8;43m'"$*"'\e[m'; } ## These will be fine for now. ##
ByellowV () { printf '\e[8;43m'"$*"'\e[m'; }
BblueV () { printf '\e[8;44m'"$*"'\e[m'; }
BmagentaV () { printf '\e[8;45m'"$*"'\e[m'; }
BpurpleV () { printf '\e[8;45m'"$*"'\e[m'; }
BaquaV () { printf '\e[8;46m'"$*"'\e[m'; }
BcyanV () { printf '\e[8;46m'"$*"'\e[m'; }
BgreyV () { printf '\e[8;47m'"$*"'\e[m'; }
BwhiteV () { printf '\e[8;47m'"$*"'\e[m'; }
## ∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞ ##
``
The only thing to keep in mind is when wanting a % percent sign or a \ backslash, you need to double them up inside:
like: printf "$(Tblue "%%s")\n" 'hi'
but not for Tblue "%s\n" 'hi'
or printf "$(Tblue "%s" 'hi')\n"
Since these use printf, you can do stuff like:
printf "hi $(Tred there) man $(BaquaI "%c" '!') $(Bold 'This \\t is %%s') %s\n" "$(BgreenB 'super')" "$(Bblue mega Colorful)"
or in an echo:
echo "hi $(Tred there) man $(BaquaI "%c" '!') $(Bold 'This \\t is %s' "$(BblackB 'super')") $(Bblue mega Colorful)"
A more useful example:
printf "\t%s Volume \"%s\" is not connected.\n" "$(TwhiteB [)$(TredB Error)$(TwhiteB \]:)" "$(Tbrown $Volume)"
Or with other commands:
eval "echo 'This is OSX' | sed 's:OSX:$(Invert [)$(TaquaF OSX)$(Invert ]):'"
Or something with a bit more swank:
find . -exec stat -f "Name: $(Tbrown %%N)%t%t$(Tpurple "->")%tPermissions: $(Tgreen %%Sp)" {} \;
Use your imagination! Feel free all to use these... the only thing I ask is if someone out there types up more of them, mix/matching them, like TcyanBgreenUI, or make up your own names... can you please post them for me and let me know about the post? or email them to me at aesth1r#me.com. I'm too lazy to type up all possibilities.
Enjoy!
-- Aesthir
Related
I wrote a simple webserver which should continuously handle simultaneous requests. But, even after detaching the threads it doesn't handle simultaneous requests. Can someone help?
Webserver.pl
use HTTP::Daemon;
use threads;
my $webServer;
my $package_map = {"test" => "test"};
my $d = HTTP::Daemon->new(LocalAddr => $ARGV[0],
LocalPort => 80,
Listen => 20) || die;
print "Web Server started!\n";
print "Server Address: ", $d->sockhost(), "\n";
print "Server Port: ", $d->sockport(), "\n";
while (my $c = $d->accept) {
threads->create(\&process_req, $c)->detach();
}
sub process_req {
my $c = shift;
my $r = $c->get_request;
if ($r) {
if ($r->method eq "GET") {
my $path = $r->url->path();
my $service = $package_map->{$path};
if ($service) {
$response = $service->process_request($request);
}
}
}
$c->close;
undef($c);
}
test.pm
sub process_request
{
threads->create(\&testing)->detach();
my $response = HTTP::Response -> new (200);
$response -> header('Access-Control-Allow-Origin', '*');
$response -> content("Success");
return $response;
}
sub testing
{
my $command = 'echo "sleep 100" | ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 <dev_box>';
if (system($command) != 0) {
print "FAILED\n";
}
}
Here is code based on your example that works for me on Windows. Maybe you can show us how/where it fails for you:
#!perl
use strict;
use warnings;
use HTTP::Daemon;
use threads;
my $webServer;
#my $package_map = {"test" => "test"};
my $d = HTTP::Daemon->new(LocalAddr => $ARGV[0],
LocalPort => $ARGV[1] // 80,
Listen => 20) || die;
print "Web Server started!\n";
print "Server Address: ", $d->sockhost(), "\n";
print "Server Port: ", $d->sockport(), "\n";
while (my $c = $d->accept) {
warn "New connection";
threads->create(\&process_req, $c)->detach();
}
sub process_req {
my $c = shift;
while( my $r = $c->get_request ) {
if ($r) {
if ($r->method eq "GET") {
my $path = $r->url->path();
if (1) {
sleep 100;
$c->send_response( HTTP::Response->new(200, "OK", undef, "done\n") );
}
}
}
};
$c->close;
}
I had some working code that I've tried to multithread using the tutorial on dreamincode: http://www.dreamincode.net/forums/topic/255487-multithreading-in-perl/
The example code there seems to work fine, but I can't for the life of me work out why mine isn't. From putting in debug messages it seems to get all the way to the end of the subroutine with all of the threads, and then sit there for a while before hitting a segmentation fault and dumping the core. That being said I've also not managed to find the core dump files anywhere (Ubuntu 13.10).
If anyone has any suggested reading, or can see the error in the rather messy code below I'd be eternally grateful.
#!/usr/bin/env perl
use Email::Valid;
use LWP::Simple;
use XML::LibXML;
use Text::Trim;
use threads;
use DB_File;
use Getopt::Long;
my $sourcefile = "thislevel.csv";
my $startOffset = 0;
my $chunk = 10000;
my $num_threads = 8;
$result = GetOptions ("start=i" => \$startOffset, # numeric
"chunk=i" => \$chunk, # numeric
"file=s" => \$sourcefile, # string
"threads=i" => \$num_threads, #numeric
"verbose" => \$verbose); # flag
$tie = tie(#filedata, "DB_File", $sourcefile, O_RDWR, 0666, $DB_RECNO)
or die "Cannot open file $sourcefile: $!\n";
my $filenumlines = $tie->length;
if ($filenumlines>$startOffset + $chunk){
$numlines = $startOffset + $chunk;
} else {
$numlines = $filenumlines;
}
open (emails, '>>emails.csv');
open (errorfile, '>>errors.csv');
open (nxtlvl, '>>nextlevel.csv');
open (donefile, '>>donelines.csv');
my $line = '';
my $found = false;
my $linenum=0;
my #threads = initThreads();
foreach(#threads){
$_ = threads->create(\&do_search);
}
foreach(#threads){
$_->join();
}
close nxtlvl;
close emails;
close errorfile;
close donefile;
sub initThreads{
# An array to place our threads in
my #initThreads;
for(my $i = 1;$i<=$num_threads;$i++){
push(#initThreads,$i);
}
return #initThreads;
}
sub do_search{
my $id = threads->tid();
my $linenum=$startOffset-1+$id;
my $parser = XML::LibXML->new();
$parser->set_options({ recover => 2,
validation => 0,
suppress_errors => 1,
suppress_warnings => 1,
pedantic_parser => 0,
load_ext_dtd => 0, });
while ($linenum < $numlines) {
$found = false;
#full_line = split ',', $filedata[$linenum-1];
$line = trim(#full_line[1]);
$this_url = trim(#full_line[2]);
print "Thread $id Scanning $linenum of $filenumlines\: ";
printf "%.3f\%\n", 100 * $linenum / $filenumlines;
my $content = get trim($this_url);
if (!defined($content)) {
print errorfile "$this_url, no content\n";
}elsif (length($content)<100) {
print errorfile "$this_url, short\n";
}else {
my $doc = $parser->load_html(string => $content);
if(defined($doc)){
for my $anchor ( $doc->findnodes("//a[\#href]") )
{
$is_email = substr $anchor->getAttribute("href") ,7;
if(Email::Valid->address($is_email)) {
printf emails "%s, %s\n", $line, $is_email;
$found = true;
} else{
$link = $anchor->getAttribute("href");
if (substr lc(trim($link)),0,4 eq "http"){
printf nxtlvl "%s, %s\n", $line, $link;
} else {
printf nxtlvl "%s, %s/%s\n", $line, $line, $link;
}
}
}
}
if ($found=false){
my #lines = split '\n',$content;
foreach my $cline (#lines){
my #words = split ' ',$cline;
foreach my $word (#words) {
my #subwords = split '"',$word ;
foreach my $subword (#subwords) {
if(Email::Valid->address($subword)) {
printf emails "%s, %s\n", $line, $subword;
}
}
}
}
}
}
printf donefile "%s\n",$linenum;
$linenum = $linenum + $num_threads;
}
threads->exit();
}
In addition to sundry coding errors that mean my code should never ever be used as an example for other visitors, DB_File is not a thread-safe module.
Annoyingly, and perhaps misleadingly, it works absolutely as it should do right up until you close the threads that have been successfully accessing the file throughout your code.
There is forks::shared that should be drop in replacement for threads::shared, but how should I replace Thread::Queue?
I would like to convert following code to forks, if it is possible?
sub Qfac {
use threads;
use threads::shared;
use Thread::Queue;
my ($worker, $arrid, $arg) = #_;
$arrid ||= [];
$arg ||= {};
my %tr;
my %h :shared;
my %qe = map { $_ => Thread::Queue->new() } #$arrid;
for my $id (#$arrid) {
my $q = $qe{$id};
$tr{$id} = threads->create($arg, sub{
my $me = { id => $id };
while (my $item = $q->dequeue()) {
$me->{item} = $item;
eval { $worker->($me, \%h) };
$me->{err} = $# if $#;
my $temp = threads::shared::shared_clone($me);
{
lock (%h);
$h{$id} = $temp;
}
}
});
$tr{$id}->detach();
}
##
return sub {
my $act = shift;
if ($act eq "getshared") { return #_ ? #h{#_} : \%h }
elsif ($act eq "enqueue") { $_->enqueue(#_) for values %qe }
elsif ($act eq "getqe") { return \%qe }
elsif ($act eq "gettr") { return \%tr }
elsif ($act eq "getssize") { return threads->get_stack_size() }
elsif ($act eq "setssize") { return threads->set_stack_size(#_) }
else { die "unknown method" }
};
}
my $worker = sub {
my ($me) = #_;
my $id = $me->{id};
# $me->{foo} = "bar";
};
my $qf = Qfac($worker, [ 0 .. 10 ]);
# Send work to the thread
$qf->("enqueue", "do_something");
# ...
my $shared = $qf->("getshared");
use forks; (and its ::shared) is a drop-in replacement for use threads; (and its ::shared), and Thread::Queue uses thread::shared, so Thread::Queue will continue working just fine.
use if $ARGV[0], "forks";
use threads; # No effect under "use forks;"
use Thread::Queue;
my $q = Thread::Queue->new();
print "$$\n";
async {
print "$$\n";
print "$_\n" while $_ = $q->dequeue();
};
$q->enqueue($_) for 1..4;
$q->end();
$_->join() for threads->list();
$ perl x.pl 0
6047
6047
1
2
3
4
$ perl x.pl 1
6054
6056
1
2
3
4
(You'll need to add use forks::shared; with older versions for forks.)
I have a hard-coded if loops that looks like this:
my $tp = 0;
my $fp = 0;
if ( $myhash{$pred}
|| $myhash{$pred1}
|| $myhash{$pred2}
|| $myhash{$pred3}
|| $myhash{$pred4}
|| $myhash{$pred5}
|| $myhash{$pred6} )
{
$tp++;
}
else {
$fp++;
}
How can I do that in for loops?
I tried the following but it give different result in total of fp and tp:
my $tp=0;
my $fp=0;
my #allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5);
foreach my $allpred ( #allpreds ) {
if ( $myhash{$allpred} ) {
$tp++;
}
}
if ( !myhash{$pred} ) {
$fp++;
}
my $tp=0;
my $fp=0;
my $count=0;
my #allpreds = ($pred,$pred1,$pred2,$pred3,$pred4,$pred5);
foreach my $allpred ( #allpreds ) {
if ( $myhash{$allpred} ) {
$count++;
}
}
if ($count>0) { $tp=1; } else { $fp=1; }
This is somewhat more compact than some answers, but fully equivalent.
my $tp = 0;
my $fp = 0;
foreach my $allpred ($pred, $pred1, $pred2, $pred3, $pred4, $pred5)
{
$tp++, last if ($myhash{$allpred});
}
$fp = !$tp;
It is not clear that the variable $fp earns its keep when !$tp is almost as simple to write.
Test code - change the settings on the RHS of the fat commas to change the behaviour of the test.
use strict;
use warnings;
my $pred = "";
my $pred1 = "1";
my $pred2 = "2 2";
my $pred3 = "3 3 3";
my $pred4 = "4 4 4 4";
my $pred5 = "5 5 5 5 5";
my %myhash = ( $pred1 => 0, $pred2 => 0, $pred3 => 0, $pred4 => 0, $pred5 => 1 );
my $tp = 0;
my $fp = 0;
foreach my $allpred ($pred, $pred1, $pred2, $pred3, $pred4, $pred5)
{
$tp++, last if ($myhash{$allpred});
}
$fp = !$tp;
printf "%d:%d\n", $tp, $fp;
grep will return a true value when any one or more of its inputs returns true for it's statement, basically allowing it to act like a chain of ||'ed statements, except that it won't short circuit.
my #allpreds = ($pred, $pred1, $pred2, $pred3, $pred4, $pred5, $pred6);
if (grep { $myhash{$_} } #allpreds) {
$tp++;
}
else {
$fp++;
}
Using grep this way can be a bit confusing so a more explicit way is to use List::MoreUtils any
use List::MoreUtils qw(any);
my #allpreds = ($pred, $pred1, $pred2, $pred3, $pred4, $pred5, $pred6);
if (any { $myhash{$_} } #allpreds) {
$tp++;
}
else {
$fp++;
}
I have the following command which displays to me my current IP address:
ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'
I'd like to be able to wrap this command into an alias such as:
alias myip="ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'"
or even a function like so:
function myip() { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }' }
However, none of these solutions work and I get this error:
syntax error near unexpected token ``{ifconfig'
I've tried this:
alias myip='ifconfig -a | awk '\''BEGIN{ count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'\'''
but no luck.
How would I be able to accomplish this task?
1) Your function needs a ; before the closing }
function myip() { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'; }
HERE --^
2) You only need either function or (), but not both. (Although this depends on your shell.)
function myip { ifconfig -a | awk 'BEGIN { count=0; } { if ( $1 ~ /inet/ ) { count++; if( count==2 ) { print $2; } } }'; }
3) You probably didn't unalias your previous attempt before you did your function attempt
unalias myip
After making those changes, the function should work without a syntax error.