g | x | w | all
Bytes Lang Time Link
016Japt250829T094146ZShaggy
023Pip250828T222707ZDLosc
026Ly220716T083423Zcnamejj
013Vyxal s220716T032527ZnaffetS
286PHP151106T172457Zundefine
103MATLAB151105T155914Zslvrbld
137JavaScript ES6151104T234404Zedc65
033CJam151104T164053ZMartin E
174Python 2151105T082809ZDLosc
092Ruby151105T073746ZCristian
023TeaScript151104T202603ZDowngoat
024CJam151105T035848ZDennis
134Mathematica151104T223504ZLegionMa
118Bash + common linux utils151104T202728ZDigital
022Pyth151104T195954ZMaltysen
118Julia151104T174231ZAlex A.

Japt, 16 bytes

csV ò ËnG d
;¬oE

Try it

Pip, 23 bytes

CFH J*ZUW$.A*aTBbFI_NPA

Requires version 1.3 (currently in alpha at the time of writing) for FH.

Try It Online!

Explanation

CFH J*ZUW$.A*aTBbFI_NPA
             a           First command-line argument (the string)
           A*            ASCII code of each character
              TB         Convert to base...
                b        ... second command-line argument (the base)
         $.              Fold on concatenation
       UW                Unweave, giving a pair of every-other-character lists
      Z                  Zip the lists together, giving a list of pairs of
                         consecutive characters and discarding the odd one out
    J*                   Join each pair into a string
 FH                      Convert from hex to decimal
C                        Convert from charcode to character
                 FI      Filter on this function:
                   _N      Is the character in...
                     PA    ... the printable ASCII characters?
                         Autoprint, concatenating together (implicit)

Ly, 26 bytes

ir[sp>lS<]>ry[puu' oy1G*]p

Try it online!

This code uses the S instruction to convert the codepoints to digits one input character at a time. Then it just prints pairs of digits delimited with spaces from the accumulation stack.

ir
i                          - read input as codepoints
 r                         - reverse stack
  [      ]                 - for each input char/codepoint...
   sp                      - stash codepoint and delete
     >l                    - switch to accum stack, load codepoint
       S                   - convert codepoint to digits
        <                  - switch back to input stack
          >r               - switch to accum stack, reverse digits
            y[          ]  - loop until stack size is <2
              p            - delete loop iterator artifact
               uu          - print two digits
                 ' o       - print a space
                    y1G    - is the stack size >1?
                       *   - multiple to combine top two of stack
                         p - print iterator artifact

Vyxal s, 13 bytes

C$vτHfṅǒHCkQ↔

Try it Online!

PHP - 286 bytes

Put the string in $s and the integer in $b.

<?php $s=$_GET["s"];$b;$m="array_map";echo implode($m(function($v){return ctype_print($v)?$v:"";},$m("chr",$m("hexdec",str_split(strlen(implode($a=$m(function($v){global$b;return base_convert($v,16,$b);},$m("dechex",$m("ord",str_split($s))))))%2==1?substr(implode($a),0,-1):$a,2)))));?>

Pass the value to GET["s"].

MATLAB, 103 bytes

function k(s,n),b=dec2base(s,n)';b(~cumsum(b-'0',1))='';c=base2dec(textscan(b,'%2c'),16)';char(c(c>31))

I've written a function k that takes a string s and an integer n as input. e.g.:

k('Hello, World!',6)

gives

 E001R"31$E

Most annoying thing I had to work around is leading zeros showing up when converting to base n. Getting these out of the array that was to be split after every 2nd character cost quite a lot of bytes. Not sure if it is possible to save any more bytes using this approach.

JavaScript (ES6), 137 147

Using the most verbose functions available in JavaScript

f=(s,b)=>alert(s.replace(/./g,x=>x.charCodeAt().toString(b)).match(/../g).map(x=>(x=String.fromCharCode('0x'+x))<='~'&x>' '?x:'').join``)

// Just for test purpose, redefine alert()
alert=x=>document.write('<pre>'+x+'</pre>')

f('Hello, World!',6)
f('PORK',3)

CJam, 33 bytes

q~:i\fb:~0+2/W<Gfb:c' ,-'ÿ),127>-

Takes input in the form 6 "Hello, World!". Test it here.

See Dennis's answer for a similar but better solution with a nice explanation.

Python 2, 174 bytes

def J(a,b,i=0):
 h=r=''
 B=lambda n,b:n*'x'and B(n/b,b)+chr(48+n%b+7*(n%b>9))
 for c in a:h+=B(ord(c),b)
 while i<len(h):v=int(h[i:i+2],16);r+=chr(v)*(31<v<127);i+=2
 print r

Try it here

Not really the best tool for the job. Since Python has no convert-to-arbitrary-base function, I had to implement my own. That was fun, at least--particularly finding a [marginally] shorter expression for the digits than "0123456789ABCDEF"[n%b]. For iterating over two characters at a time, I found a while loop was slightly shorter than a functional approach.

181 bytes as a full program:

B=lambda n,b:n*'x'and B(n/b,b)+chr(48+n%b+7*(n%b>9))
a=raw_input()
b=input()
h=r=''
for c in a:h+=B(ord(c),b)
i=0
while i<len(h):v=int(h[i:i+2],16);r+=chr(v)*(31<v<127);i+=2
print r

Ruby 92

->s,n{o=''
s.chars.map{|x|x.ord.to_s n}.join.scan(/../).map{|x|x>?2&&x<?8&&o<<x.to_i(16)}
o}

Online test here.

TeaScript, 23 bytes

TeaScript is JavaScript for golfing

£lc¡T(y©K(2)ßC(P(l,16±µ

Relatively straight-forward but delightfully short. I can probably golf down a few more characters with some more operators. A few other new features might also be able to be used to cut down some bytes.

Ungolfed && Explanation

x.l(#
    l.c().T(y)
).K(2)
.m(#
    C(
      P(l,16)
    )
).j``

CJam, 24 bytes

l:irifbe_2/{Gbc',32>&}/

Note that there is a DEL character (0x7F) between ' and ,. Try it online in the CJam interpreter.

How it works

l:i                     Read a line from STDIN and cast each char to integer. 
   ri                   Read another integer (base) from STDIN.
     fb                 Convert each integer from line 1 to that base.
       e_2/             Flatten and split into chunks of length 2.
                        If the last chunk has only one element, it will get
                        converted into a control character, which will be
                        removed later.
          {         }/  For each digit pair:
           Gb             Convert the pair from base 16 to integer.
             c            Cast to character.
              ',          Push the string of ASCII characters up to '~'.
                32>       Remove the first 32 (control characters).
                   &      Intersect.

Mathematica, 134 bytes

Print@FromCharacterCode@Select[#~FromDigits~16&/@StringPartition[""<>ToCharacterCode@InputString[]~IntegerString~Input[],2],31<#<127&]

If a function is allowed:

Mathematica, 112 bytes

FromCharacterCode@Select[#~FromDigits~16&/@StringPartition[""<>ToCharacterCode@#~IntegerString~#2,2],31<#<127&]&

Bash + common linux utils, 118

printf %s "$1"|xxd -p|sed -r "s/../\U& /g;y/ /n/;s/^/dc -e$2o16i/e;s/../& /g;s/ .$//;"|xxd -rp|sed 's/[^[:print:]]//g'

Pyth - 22 bytes

Hope to golf a lot more, pretty straightforward.

sfq3l`TmCid16csjRQCMz2

Try it online here.

Julia, 118 bytes

f(s,n)=join(map(i->(c=string(Char(parse(Int,i,16))))^isprint(c),matchall(r"..",join(map(i->base(n,Int(i)),[s...])))))

Ungolfed:

function f(s::AbstractString, n::Integer)
    # Construct an array of ASCII codes in base n
    v = map(i -> base(n, Int(i)), [s...])

    # Join into a string and get all pairs, truncating
    # to an even length
    m = matchall(r"..", join(v))

    # Parse each pair as an integer in base 16, get the
    # character associated with that code point, convert
    # to a string, and include if it's printable
    x = map(i -> (c = string(Char(parse(Int, i, 16)))^isprint(c), m)

    # Join as a string and return
    return join(x)
end